Android 12安装应用出错:For security reasons, the system cannot issue a Uri permission

问题场景:

在Android 12平台中通过自研多媒体应用打开U盘安装apk程序报URI权限错误

05-25 09:42:23.335  2753  2753 E AndroidRuntime: FATAL EXCEPTION: main
05-25 09:42:23.335  2753  2753 E AndroidRuntime: Process: com.android.packageinstaller, PID: 2753
05-25 09:42:23.335  2753  2753 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.packageinstaller/com.android.packageinstaller.InstallStart}: java.lang.SecurityException: UID 10024 does not have permission to content://com.example.media.fileProvider/all_files/storage/762F-2749/YouTube_18.03.36_Apkpure.apk [user 0]
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3707)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3864)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2253)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:106)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:201)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:288)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:7870)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: Caused by: java.lang.SecurityException: UID 10024 does not have permission to content://com.sx.tv.media.fileProvider/all_files/storage/762F-2749/YouTube_18.03.36_Apkpure.apk [user 0]
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.os.Parcel.createExceptionOrNull(Parcel.java:2425)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.os.Parcel.createException(Parcel.java:2409)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.os.Parcel.readException(Parcel.java:2392)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.os.Parcel.readException(Parcel.java:2334)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.IActivityTaskManager$Stub$Proxy.startActivity(IActivityTaskManager.java:2326)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.Instrumentation.execStartActivity(Instrumentation.java:1758)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.Activity.startActivityForResult(Activity.java:5422)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.Activity.startActivityForResult(Activity.java:5380)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.Activity.startActivity(Activity.java:5766)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.Activity.startActivity(Activity.java:5719)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at com.android.packageinstaller.InstallStart.onCreate(InstallStart.java:150)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.Activity.performCreate(Activity.java:8069)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.Activity.performCreate(Activity.java:8049)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1341)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3688)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	... 12 more
05-25 09:42:23.335  2753  2753 E AndroidRuntime: Caused by: android.os.RemoteException: Remote stack trace:
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at com.android.server.uri.UriGrantsManagerService.checkGrantUriPermissionUnlocked(UriGrantsManagerService.java:1256)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at com.android.server.uri.UriGrantsManagerService.checkGrantUriPermissionFromIntentUnlocked(UriGrantsManagerService.java:621)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at com.android.server.uri.UriGrantsManagerService.access$1000(UriGrantsManagerService.java:107)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at com.android.server.uri.UriGrantsManagerService$LocalService.checkGrantUriPermissionFromIntent(UriGrantsManagerService.java:1412)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 	at com.android.server.wm.ActivityStarter$Request.resolveActivity(ActivityStarter.java:541)
05-25 09:42:23.335  2753  2753 E AndroidRuntime: 
05-25 09:42:23.345   497   546 W ActivityTaskManager:   Force finishing activity com.android.packageinstaller/.InstallStart
05-25 09:42:23.346   497  2777 I DropBoxManagerService: add tag=system_app_crash isTagEnabled=true flags=0x2

打开UriGrantsManagerService.java中的DEBUG后,发现如下log:

URiGrantsManagerService: For security reasons, the system cannot issue a Uri permission

通过如上log和前面的AndroidRuntime的堆栈打印,定位到是checkGrantUriPermissionUnlocked函数里面做的权限检查,如下是checkGrantUriPermissionUnlocked函数中做判断的部分代码

    /**
     * Check if the targetPkg can be granted permission to access uri by
     * the callingUid using the given modeFlags.  Throws a security exception
     * if callingUid is not allowed to do this.  Returns the uid of the target
     * if the URI permission grant should be performed; returns -1 if it is not
     * needed (for example targetPkg already has permission to access the URI).
     * If you already know the uid of the target, you can supply it in
     * lastTargetUid else set that to -1.
     */
    private int checkGrantUriPermissionUnlocked(int callingUid, String targetPkg, GrantUri grantUri,
            int modeFlags, int lastTargetUid) {
        if (!Intent.isAccessUriMode(modeFlags)) {
            return -1;
        }

        if (targetPkg != null) {
            if (DEBUG) Slog.v(TAG, "Checking grant " + targetPkg + " permission to " + grantUri);
        }

        // If this is not a content: uri, we can't do anything with it.
        if (!ContentResolver.SCHEME_CONTENT.equals(grantUri.uri.getScheme())) {
            if (DEBUG) Slog.v(TAG, "Can't grant URI permission for non-content URI: " + grantUri);
            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())) {
                // 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;
            }
        }

解决方案

通过上面代码可以看出,针对是SYSTEM_ID和ROOT_UID应用,如果不是指定的授权包名就会直接返回-1,即not allow。所以要解决该问题,只要把自己的应用包名加进去就行了

--- a/Android/frameworks/base/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/Android/frameworks/base/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -1099,7 +1099,8 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
             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.android.settings.module_licenses".equals(grantUri.uri.getAuthority())
+                    || "com.example.media.fileProvider".equals(grantUri.uri.getAuthority())) {
                 // Exempted authority for
                 // 1. cropping user photos and sharing a generated license html
                 //    file in Settings app

### HTML内容无法通过Pinata公共网关提供服务的原因 当尝试通过Pinata公共网关访问HTML文件时,可能会遇到显示不正常的情况。这是因为浏览器的安全策略阻止了跨域请求中的JavaScript执行[^1]。具体来说,由于同源政策(Same-Origin Policy),如果HTML页面试图加载来自不同域名、协议或端口的资源,则这些请求会被阻断。 另外一个重要因素在于IPFS(InterPlanetary File System)的设计初衷并非为了直接托管动态Web应用程序。因此,在默认情况下,Pinata公共网关不会处理HTTP头部设置来支持正确的MIME类型解析和CORS(Cross-Origin Resource Sharing)配置[^2]。 ### 解决方案 #### 方法一:使用自定义网关 创建并部署自己的IPFS节点作为私有网关可以完全控制服务器响应头信息。这允许调整必要的HTTP header以确保兼容性和安全性,从而使得HTML及相关静态资产能够被正确渲染[^3]。 ```bash ipfs daemon --enable-gateway-dir-listing=true ``` 此命令启动了一个带有目录列表功能启用选项的本地IPFS守护进程实例,它有助于更好地管理和分发网页内容。 #### 方法二:修改元数据和服务工作流 对于希望继续利用Pinata公共服务的朋友而言,可以通过上传前优化项目结构的方式绕过上述限制。例如,将所有依赖项打包成单个文件或将整个站点转换为SPA (Single Page Application)[^4]。 ```javascript // 使用Webpack或其他构建工具进行打包 const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } }; ``` 这样做不仅简化了发布流程还提高了性能表现;同时因为减少了对外部资源的需求所以降低了因跨域问题而导致失败的风险。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值