从我自己的应用程序查询我自己的 ContentProvider 时获得权限拒绝

Getting a Permission Denial when querying my own ContentProvider from my own App

在我的一个应用程序中,我使用 ContentProvider 来保存和恢复信息。此 ContentProvider 由主应用程序以及一些服务使用,但它们都在同一个 apk 中,并且所有服务都位于默认(主)进程中。

我的内容提供者在我的清单中是这样声明的:

    <provider android:name="sample.provider.SampleProvider"
              android:authorities="sample.provider"
              android:exported="false"
              android:enabled="true">
    </provider>

我的一个 类 注册为 URI 上的观察者,当通知更改时,我直接查询提供者以更新内部值。

@Override
public void onChange(boolean selfChange, @Nullable Uri uri) {
    if (uri == null) {
        return;
    }
    try {
        Cursor updated = mContentResolver.query(uri, null, null, null, null);
        // ... working with the cursor here
    } catch (Exception e) {
        e.printStackTrace();
    }
}

此代码总是失败,但有以下例外情况

java.lang.SecurityException: Permission Denial: reading sample.provider.SampleProvider uri 
    content://sample.provider/infos/FOO from pid=0, uid=1000 requires the provider be 
    exported, or grantUriPermission()
      at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:605)
      at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:480)
      at android.content.ContentProvider$Transport.query(ContentProvider.java:211)
      at android.content.ContentResolver.query(ContentResolver.java:491)
      at android.content.ContentResolver.query(ContentResolver.java:434)
      at sample.foo.Bar.onChange(Bar.java:331)
      at android.database.ContentObserver.onChange(ContentObserver.java:145)
      at android.database.ContentObserver.dispatchChange(ContentObserver.java:196)
      at android.database.ContentObserver.-wrap0(ContentObserver.java)
      at android.database.ContentObserver$Transport.onChange(ContentObserver.java:231)
      at android.database.IContentObserver$Stub.onTransact(IContentObserver.java:62)
      at android.os.Binder.execTransact(Binder.java:453)

请注意,当我在清单中使用 exported="true" 时,一切正常

在调查这个问题后,我发现我的观察者是从另一个应用程序调用的(我的猜测是,它是 OS 直接调用我的观察者),这意味着当我进行查询时我不在我自己的应用程序的上下文,即使它是我自己的代码 运行。

我通过在对象中创建处理程序并在检测到观察到的 URI 发生变化时发送消息来解决此问题