Permission Denial: opening provider xxx that is not exported from UID 1000解决方案

本文讲述了在Android系统中使用FileProvider时遇到的AccessDeniedException,特别是当应用设置为系统应用与非系统应用混合时。提供了两种解决方案:一是调整应用的android.uid.system属性;二是修改framework源码中的UriGrantsManagerService,添加FileProvider的过滤条件。
摘要由CSDN通过智能技术生成

问题场景:

我们在使用FileProvider时遇到这个错误

java8.nio.file.AccessDeniedException: content://com.xxx.xxx.provider/external_files/DCIM/screen
shot/1709621636303.png: java.lang.SecurityException: Permission Denial: opening provider
androidx.core.content.FileProvider from ProcessRecord/7fdc1b8 4501:) that is not exported from UID 1000 

这个问题一般是应用设置了‘android:sharedUserId="android.uid.system" 变成了系统应用。
(1)在高版本的Android系统上安装此应用提示出现这个错误
(2)利用FileProvider向外部的非系统应用(UID不是系统的UID)提供资源数据

如果大家已经确保权限什么的都没有任何问题,接着往下看


如何解决

方案一

如果是上面描述的第二种情况,把两个应用都添加android.uid.system,都变成系统应用,拥有相同的UID。或者两个应用都去掉android.uid.system,这样两个应用都是普通应用。就能使用FileProvider分享数据。

总之不改系统源码情况下,不能一个是系统应用,另一个是非系统应用,这种情况使用FileProvider肯定报上面的错误。

方案二

如果就必须是:系统应用和非系统应用之间使用FileProvider,或者文章开头提到的(1)中描述的情况。那么就需要改framework源码了。

Android 11-13
frameworks\base\services\core\java\com\android\server\uri\UriGrantsManagerService.java
#checkGrantUriPermissionUnlocked()方法

private int checkGrantUriPermissionUnlocked(int callingUid, String targetPkg, GrantUri grantUri,
            int modeFlags, int lastTargetUid) {
        if (!Intent.isAccessUriMode(modeFlags)) {
            return -1;
        }

        ......

        // Bail early if system is trying to hand out permissions directly; it
        // must always grant permissions on behalf of someone explicit.
        final int callingAppId = UserHandle.getAppId(callingUid);
        if ((callingAppId == SYSTEM_UID) || (callingAppId == ROOT_UID)) {
            if ("com.android.settings.files".equals(grantUri.uri.getAuthority())
                    || "com.android.rk.fileprovider".equals(grantUri.uri.getAuthority())
                    || "com.rockchips.mediacenter.fileprovider".equals(grantUri.uri.getAuthority())
                    || "com.android.settings.module_licenses".equals(grantUri.uri.getAuthority())
                    || "com.xxx.xxx.fileprovider".equals(grantUri.uri.getAuthority()) /*新增一个URI过滤*/) {
                // Exempted authority for
                // 1. cropping user photos and sharing a generated license html
                //    file in Settings app
                // 2. sharing a generated license html file in TvSettings app
                // 3. Sharing module license files from Settings app
            } else {
                Slog.w(TAG, "For security reasons, the system cannot issue a Uri permission"
                        + " grant to " + grantUri + "; use startActivityAsCaller() instead");
                return -1;
            }
        }
        

在上面的if判断中,新增一个过滤条件。其中com.xxx.xxx.fileprovider就是想要过滤的FileProvider的authorities

Android10
frameworks\base\services\core\java\com\android\server\uri\UriGrantsManagerService.java
#checkGrantUriPermission()方法

看网上的参考资料
Android8
frameworks\base\services\core\java\com\android\server\am\a\ActivityManagerService.java
#checkGrantUriPermissionLocked()方法

总之改的都是在if条件中增加对应fileProvider的过滤条件,让系统不要截停这个fileProvider的URI资源

然后编译系统即可


参考资料:

Android 8.1安装以上app包解析包错误Permission Denial: that is not exported from UID 1000)

Permission Denial: opening provider that is not exported from UID 1000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值