最近遇到一个怪事,访问ContentProvider的call方法一直报这个错,经过不断的研究,终于知道问题在哪了,这里做个记录;
比如,在进程A中调用进程B,进程B再去访问ContentProvider的call、query等方法,而call、query等方法里面又调用了ContentProvider.getCallingPackage(),那么就会报这个错;
先看下ContentProvider.getCallingPackage()的源码,
public final @Nullable String getCallingPackage() {
final AttributionSource callingAttributionSource = getCallingAttributionSource();
return (callingAttributionSource != null)
? callingAttributionSource.getPackageName() : null;
}
public final @Nullable AttributionSource getCallingAttributionSource() {
final AttributionSource attributionSource = mCallingAttributionSource.get();
if (attributionSource != null) {
mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(),
attributionSource.getPackageName());
}
return attributionSource;
}
这里可以看到源码中会拿调用方的包名和uid进行检查,查看是否配对,如果不是,就会抛出异常
/**
* @deprecated Use {@link PackageManager#getPackageUid} instead
*/
@Deprecated
public void checkPackage(int uid, @NonNull String packageName) {
try {
if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
throw new SecurityException(
"Package " + packageName + " does not belong to " + uid);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
问题就出在进程A调用了进程B,进程B去访问ContentProvider.getCallingPackage(), 然后Binder.getCallingUid拿到的是进程A的身份的uid,而不是进程B的身份uid
下面贴下如何解决的?
val token = Binder.clearCallingIdentity()
val client =
UMSEnv.applicationContext.contentResolver.acquireUnstableContentProviderClient(
providerAuthorityUri
)
kotlin.runCatching {
val extras = Bundle()
extras.putInt(KEY_HOST_PID, pid)
val bundle = client?.call(METHOD_QUERY_HOST_PACKAGE_NAME, null, extras)
client?.close()
hostPackageName = bundle?.getString(KEY_HOST_PACKAGE_NAME)
}.onFailure {
client?.close()
LogUtils.e(TAG, "queryHostPackageName, exception: $it")
it.printStackTrace()
}
Binder.restoreCallingIdentity(token)
看到上述代码了吗?解决问题的关键方法在于call()前后加上代码
Binder.clearCallingIdentity()
Binder.restoreCallingIdentity(token)
目的就是清除Binder中存储的进程A的身份,这2句代码需要成对使用哦!
下面是相关问题的链接:
Android ContentProvider调用报错"Bad call: specified package xxx under uid 10032 but it is really 10001"及Binder权限问题分析
https://www.jianshu.com/p/a609b965364b 文章来源:https://uudwc.com/A/AAk5g
好了又可以愉快玩耍了。文章来源地址https://uudwc.com/A/AAk5g