从同一应用程序内调用时内容提供者的权限被拒绝
permission denial for content provider when called from within the same app
我只有一个应用程序。它有一个 未导出 的内容提供者(我不希望其他应用程序访问该内容)到目前为止我一直在成功使用该内容提供者。
我创建了一个内容观察器来更新 TextView。 onChange
方法在内容更改时被调用并尝试重新查询该内容。那时它会收到如下所示的安全异常:
java.lang.SecurityException: Permission Denial: reading org.sil.lcroffline.data.DataProvider uri content://org.sil.lcroffline/users/by_account_name/5555544444 from pid=0, uid=1000 requires the provider be exported, or grantUriPermission()
这是生成它的代码:
@Override
public void onChange(boolean selfChange, Uri uri) {
Cursor c = null;
try {
c = mContentResolver.query(UserEntry.buildUserPhoneUri(mAccount.name), null, null, null, null);
// do stuff with the data in the cursor
} finally {
if (c != null) c.close();
}
}
URI 看起来格式正确,我认为在内容提供程序中匹配它没有问题。
上面的代码在应用程序中以编程方式调用时工作正常,只有当它由观察到的数据的变化触发时才会发生异常。
如何从同一个应用程序中获得拒绝权限,我该如何解决这个问题?
查看清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.sil.lcroffline">
<!-- To communicate with LCR -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Required because we're manually creating a new account. -->
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".authentication.LoginActivity"
android:label="@string/app_name"
android:exported="true">
</activity>
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme.NoActionBar"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ReportActivity"
android:parentActivityName=".MainActivity"></activity>
<service android:name=".authentication.AuthenticatorService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
<provider
android:authorities="@string/data_authority"
android:name=".data.DataProvider"
android:exported="false" />
<service
android:name=".data.SyncService"
android:exported="true"
android:process=":sync">
<intent-filter>
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
</application>
</manifest>
原来这是我没有在ContentObserver
中使用Handler
造成的
当您不将处理程序传递给内容观察器时,将直接调用 onChange
方法,而不是通过处理程序发布调用它的消息。这一切都很好,除了在那种情况下调用 onChange
方法的进程是系统 OS,它没有查询我的内容提供者的必要权限。
为了解决这个问题,我更改了创建内容观察器的代码:
mUserObserver = new ContentObserver(null) {
// override onChange methods here
}
为此:
mUserObserver = new ContentObserver(new Handler()) {
// override onChange methods here
}
给我提供了线索
我只有一个应用程序。它有一个 未导出 的内容提供者(我不希望其他应用程序访问该内容)到目前为止我一直在成功使用该内容提供者。
我创建了一个内容观察器来更新 TextView。 onChange
方法在内容更改时被调用并尝试重新查询该内容。那时它会收到如下所示的安全异常:
java.lang.SecurityException: Permission Denial: reading org.sil.lcroffline.data.DataProvider uri content://org.sil.lcroffline/users/by_account_name/5555544444 from pid=0, uid=1000 requires the provider be exported, or grantUriPermission()
这是生成它的代码:
@Override
public void onChange(boolean selfChange, Uri uri) {
Cursor c = null;
try {
c = mContentResolver.query(UserEntry.buildUserPhoneUri(mAccount.name), null, null, null, null);
// do stuff with the data in the cursor
} finally {
if (c != null) c.close();
}
}
URI 看起来格式正确,我认为在内容提供程序中匹配它没有问题。
上面的代码在应用程序中以编程方式调用时工作正常,只有当它由观察到的数据的变化触发时才会发生异常。
如何从同一个应用程序中获得拒绝权限,我该如何解决这个问题?
查看清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.sil.lcroffline">
<!-- To communicate with LCR -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Required because we're manually creating a new account. -->
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".authentication.LoginActivity"
android:label="@string/app_name"
android:exported="true">
</activity>
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme.NoActionBar"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ReportActivity"
android:parentActivityName=".MainActivity"></activity>
<service android:name=".authentication.AuthenticatorService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
<provider
android:authorities="@string/data_authority"
android:name=".data.DataProvider"
android:exported="false" />
<service
android:name=".data.SyncService"
android:exported="true"
android:process=":sync">
<intent-filter>
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
</application>
</manifest>
原来这是我没有在ContentObserver
Handler
造成的
当您不将处理程序传递给内容观察器时,将直接调用 onChange
方法,而不是通过处理程序发布调用它的消息。这一切都很好,除了在那种情况下调用 onChange
方法的进程是系统 OS,它没有查询我的内容提供者的必要权限。
为了解决这个问题,我更改了创建内容观察器的代码:
mUserObserver = new ContentObserver(null) {
// override onChange methods here
}
为此:
mUserObserver = new ContentObserver(new Handler()) {
// override onChange methods here
}