无法从其他应用访问customProvider.它说它缺少已有的权限

kac*_*e91 1 sqlite android android-contentprovider

我正在尝试使用自定义内容提供程序创建一个从另一个应用程序访问SQLite表的应用程序.我收到以下错误:

java.lang.SecurityException: Permission Denial: reading com.example.carlos.gymlog.MiContentProvider uri content://mi.uri.porquesi/sesiones from pid=2375, uid=10064 requires android.permission.permRead, or grantUriPermission()
Run Code Online (Sandbox Code Playgroud)

但是,我的"发件人"应用程序(具有数据库的应用程序)已具有所需的权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.carlos.gymlog" >

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/MiTema" >
        <activity
            android:name=".Principal"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider android:name="MiContentProvider"
            android:authorities="mi.uri.porquesi"
            android:readPermission="android.permission.permRead"
            android:exported="true"
            android:grantUriPermissions="true"> </provider>

    </application>

</manifest>
Run Code Online (Sandbox Code Playgroud)

这是导致"receiver"应用程序(尝试访问另一个)的错误的代码:

ArrayList<Sesion> sacarDatos(Context c){

        Uri cUri = Uri.parse("content://mi.uri.porquesi/sesiones");
        ContentProviderClient miCP = c.getContentResolver().acquireContentProviderClient(cUri);

        ArrayList<Sesion> sesiones = null;
        try {
            Cursor cur  = miCP.query(cUri, null, null, null, null);
            sesiones = new ArrayList<Sesion>();
            cur.moveToFirst();
            Sesion sesion = null;
            do {
                sesion = new Sesion(cur.getInt(0),cur.getInt(1),cur.getInt(2),cur.getInt(3));
                sesiones.add(sesion);
            } while (cur.moveToNext());

        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return sesiones;
    }
Run Code Online (Sandbox Code Playgroud)

最后,这是我的自定义内容提供商:

public class MiContentProvider extends android.content.ContentProvider {

    private static final String uri = "content://mi.uri.porquesi";

    public static final Uri CONTENT_URI = Uri.parse(uri);


    @Override
    public boolean onCreate() {

        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

        BaseDatosHelper miBD = new BaseDatosHelper(getContext(), "SESIONES", null, 1);
        SQLiteDatabase db = miBD.getWritableDatabase();
        SQLiteQueryBuilder qb  = new SQLiteQueryBuilder();
        qb.setTables("SESIONES");

        Cursor cur = qb.query(db,projection,selection,selectionArgs,"","",sortOrder);
        cur.setNotificationUri(getContext().getContentResolver(),uri);
        return cur;
    }
Run Code Online (Sandbox Code Playgroud)

(其他方法如insert()没有实现,它们只返回null或者它是什么,我只想选择不插入数据的数据).

编辑:

我的应用A有

 <provider android:name="MiContentProvider"
        android:authorities="mi.uri.porquesi"
        android:exported="true"
        android:permission="mi.permision"
        android:grantUriPermissions="true"> </provider>
    <permission
        android:name="mi.permision"
        />
Run Code Online (Sandbox Code Playgroud)

(只是一个随机的时间名称)

在应用程序B中,我已经包括在内

<uses-permission android:name="mi.permision"/>
Run Code Online (Sandbox Code Playgroud)

但是,现在我得到:

java.lang.SecurityException: Permission Denial: opening provider com.example.carlos.gymlog.MiContentProvider from ProcessRecord{335efe6e 3116:com.example.carlos.sample/u0a67} (pid=3116, uid=10067) requires mi.permision or mi.permision
Run Code Online (Sandbox Code Playgroud)

因此它认识到我需要我的自定义权限,但它无法识别我的应用B正在使用它.为什么??

Com*_*are 5

假设我们有App A和App B. App A有ContentProvider; 应用程序B想要使用ContentProvider来自应用程序A.并且,您希望ContentProvider使用自定义权限来保护.

应用A 在其清单中需要一个<permission>元素,并在android:name属性中包含您的自定义权限名称.不要android.permission在该自定义权限名称上使用前缀,因为您不是Android开源项目的开发人员.为您的应用使用命名空间,例如com.kace91.permission.AND_REMEMBER_THAT_CUSTOM_PERMISSIONS_HAVE_SECURITY_ISSUES.

应用程式A然后需要的属性,在所述<provider>清单元素,其具有匹配的名称的值android:name的属性<permission>元素.要么android:permission用来保护所有操作,要么有两个自定义权限并使用android:readPermissionandroid:writePermission.不要简单地使用android:readPermission,因为这意味着任何应用都可以在ContentProvider未经许可的情况下修改,并且这不太可能是用户想要的.

应用A还需要android:exported="true"<provider>元素的属性,即第三方应用可以启动与该通信的通信ContentProvider.

然后应用B可以有一个<uses-permission>明显的元素,与android:name属性值匹配的android:name的属性<permission>从应用程序A.元素,如果你使用了两种权限,读取和写入,应用B将需要两个<uses-permission>要素.

然后,如果在App B之前安装App A,并且用户同意授予App B保留自定义权限的权限,则App B将能够在App A上执行指定的操作ContentProvider.

而且,正如我的评论中所述,自定义权限存在安全问题.