android 解决java.lang.SecurityException: Package com.xxx.xxx does not belong to 1000

最近遇到一个怪事,访问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://blog.csdn.net/msn465780/article/details/131035276

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年09月25日 03:35
TIOBE 9月编程语言榜出炉!这个语言强势而出,Java地位不保?搞笑!
下一篇 2023年09月25日 03:39