无法从其他应用访问customProvider。它说它已经缺少权限

时间:2015-02-01 18:10:02

标签: android sqlite 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()

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

<?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>

这是导致&#34;接收器&#34;中错误的代码。应用程序(试图访问另一个的应用程序):

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;
    }

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

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;
    }

(其他方法如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"
        />

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

在应用B中,我已经包含了

<uses-permission android:name="mi.permision"/>

然而,现在我得到了:

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

因此它承认我需要我的自定义权限,但它不会识别我的应用B正在使用它。为什么?

1 个答案:

答案 0 :(得分:5)

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

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

App A需要一个the <provider> manifest element上的属性,该属性的值与android:name元素的<permission>属性的名称相匹配。使用android:permission来保护所有操作,或使用两个自定义权限并使用android:readPermissionandroid:writePermission不要只使用android:readPermission,因为这意味着任何应用都可以在未经许可的情况下修改ContentProvider,而且这不太可能是用户想要的。

应用A还需要android:exported="true"元素上的<provider>属性,表示第三方应用可以发起与ContentProvider的通信。

然后,应用B可以拥有a <uses-permission> manifest elementandroid:name属性值与应用A中android:name元素的<permission>属性相匹配。如果您使用了两个权限,读取和写入,App B将需要两个<uses-permission>元素。

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

并且,如我的评论中所述,there are security issues with custom permissions