Android android.uid.system的应用调用安装apk失败

2024-08-21 10:08

本文主要是介绍Android android.uid.system的应用调用安装apk失败,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

最近项目开发过程中用到安装apk的功能。把从服务器下载下来的apk安装到机器中。安装过程中遇到的问题记录一下。

问题

安装过程中提示解析软件包时出现问题。

在这里插入图片描述
说明:本文是针对运行的apk在Manifest中声明了systemuid。如果你的应用声明了"android.uid.system",而且也遇到了这个问题,恭喜你找到了本文。

android:sharedUserId="android.uid.system"

没有声明的小伙伴可以去找别的博客了。

安装apk

首先回顾一下安装的方法,android O中大家一般这样写的。

private void installApk(String path){Intent intent = new Intent(Intent.ACTION_VIEW);Uri uri = FileProvider.getUriForFile(context,"com.****.****.fileprovider",new File(path));intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);intent.setDataAndType(uri,"application/vnd.android.package-archive");context.startActivity(intent);}

然后再Manifest中声明provider

<providerandroid:authorities="com.honeywell.depponservice.fileprovider"android:name="android.support.v4.content.FileProvider"android:grantUriPermissions="true"android:exported="false"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/filepaths" /></provider>

在xml中建一个filepaths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android"><external-path path="." name="cmexternal" />
</paths>

这种方式是没问题的,但是关机问题出在了我的app声明了SYSTEM_UID。为什么这么说呢,下面继续讲。

原因

我就是按照上面的方法去安装apk,然而总是提示解析软件包时出现问题。第一反应是从服务器下载的安装包有问题,打开文件管理器,点击下载后的安装包。发现可以安装,那就说明不是安装包的问题。没办法看log吧。

03-27 18:15:16.005  1378  2744 W ActivityManager: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{f1ea483 11298:com.android.packageinstaller/u0a19} (pid=11298, uid=10019) that is not exported from UID 1000
03-27 18:15:16.006 11298 12569 W InstallStaging: Error staging apk from content URI
03-27 18:15:16.006 11298 12569 W InstallStaging: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{f1ea483 11298:com.android.packageinstaller/u0a19} (pid=11298, uid=10019) that is not exported from UID 1000
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.os.Parcel.readException(Parcel.java:2013)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.os.Parcel.readException(Parcel.java:1959)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.app.IActivityManager$Stub$Proxy.getContentProvider(IActivityManager.java:4758)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.app.ActivityThread.acquireProvider(ActivityThread.java:5860)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2530)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1783)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1396)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1249)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.content.ContentResolver.openInputStream(ContentResolver.java:969)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at com.android.packageinstaller.InstallStaging$StagingAsyncTask.doInBackground(InstallStaging.java:180)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at com.android.packageinstaller.InstallStaging$StagingAsyncTask.doInBackground(InstallStaging.java:174)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.os.AsyncTask$2.call(AsyncTask.java:333)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
03-27 18:15:16.006 11298 12569 W InstallStaging: 	at java.lang.Thread.run(Thread.java:764)

第一眼看到log时感觉是权限问题,因为有Permission Denial:字样。检查了一遍读写外部存储权限都开了啊,安装未知应用权限也打开了。可还是不行,最后索性把selinux都给关了依旧不行。无限抓狂,总之无论怎么做总会打出上面的log。在各种百度谷歌后还没有解决。一脸无奈的继续看log,看还有什么有用信息没。诶,突然发现了一行log:

ActivityManager: For security reasons, the system cannot issue a Uri permission grant to content://com.***.***.fileprovider/cmexternal/PDADownload/pda_client(4).apk [user 0]; use startActivityAsCaller() instead

最终在确认代码没问题的情况下,放大招,去源码中找答案。搜一下“For security reasons, the system cannot issue a Uri permission grant to”这段log是哪里打出来的。进到framework/base下grep.

./services/core/java/com/android/server/am/ActivityManagerService.java:9078:                Slog.w(TAG, "For security reasons, the system cannot issue a Uri permission"

十几秒后还真给搜到了。打开AMS第9078行看看。
这段log是在int checkGrantUriPermissionLocked方法中打印的,看下代码

        // 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())) {// Exempted authority for cropping user photos in Settings app} else {Slog.w(TAG, "For security reasons, the system cannot issue a Uri permission"+ " grant to " + grantUri + "; use startActivityAsCaller() instead");return -1;}}

如果你也被这个问题折磨的很痛苦,想必看到这段代码就明白原因了吧。
这尼玛被return -1了。这段代码的意思就是如果你的应用是SYSTEM_UID或者ROOT_UID就不能用content://加fileprovider的Uri。只有settings可以用。
我们可以去看下settings里面到底有没有com.android.settings.files,这样的provider。打开settings 的AndroidManifest文件。

<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="com.android.settings.files"android:grantUriPermissions="true"android:exported="false"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" />
</provider>

你会发现settings真的有。这也太坑了吧,凭什么只让settings用,所以应该怎么办呢。

  1. 去掉声明“android.uid.system”。
  2. 在AMS判断settings的地方加上你自己的uri。类似这样:
if ("com.android.settings.files".equals(grantUri.uri.getAuthority()) || "com.***.***.fileprovider".equals(grantUri.uri.getAuthority())) {
  1. 如果有人告诉你又不能去掉systemuid,又不能改framwork代码。告诉那个人:来来来,你来,你nb你来搞!

哈哈,第三条开个玩笑。这个问题当你知道答案后,感觉很简单,但是当你无论怎么调试,怎么百度谷歌都找不到原因时候,气的都要拔头发时候,不要放弃,当实在是没有办法时候就去源码里找答案,我相信总会找到答案的。希望本文可以帮到你。

最近有个新想法或许不用改源码,在声明provider时候将authorities设成settiings的:

android:authorities="com.android.settings.files"

不知道这种方式能否绕过AMS的检查,没时间去验证了,有兴趣的小伙伴可以试试,没问题的话留言说一声。如果能运行成功估计就能安装apk。

这篇关于Android android.uid.system的应用调用安装apk失败的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1092860

相关文章

利用Python操作Word文档页码的实际应用

《利用Python操作Word文档页码的实际应用》在撰写长篇文档时,经常需要将文档分成多个节,每个节都需要单独的页码,下面:本文主要介绍利用Python操作Word文档页码的相关资料,文中通过代码... 目录需求:文档详情:要求:该程序的功能是:总结需求:一次性处理24个文档的页码。文档详情:1、每个

python依赖管理工具UV的安装和使用教程

《python依赖管理工具UV的安装和使用教程》UV是一个用Rust编写的Python包安装和依赖管理工具,比传统工具(如pip)有着更快、更高效的体验,:本文主要介绍python依赖管理工具UV... 目录前言一、命令安装uv二、手动编译安装2.1在archlinux安装uv的依赖工具2.2从github

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

Java中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例解析

《Java中的分布式系统开发基于Zookeeper与Dubbo的应用案例解析》本文将通过实际案例,带你走进基于Zookeeper与Dubbo的分布式系统开发,本文通过实例代码给大家介绍的非常详... 目录Java 中的分布式系统开发基于 Zookeeper 与 Dubbo 的应用案例一、分布式系统中的挑战二

Java 缓存框架 Caffeine 应用场景解析

《Java缓存框架Caffeine应用场景解析》文章介绍Caffeine作为高性能Java本地缓存框架,基于W-TinyLFU算法,支持异步加载、灵活过期策略、内存安全机制及统计监控,重点解析其... 目录一、Caffeine 简介1. 框架概述1.1 Caffeine的核心优势二、Caffeine 基础2

使用Node.js和PostgreSQL构建数据库应用

《使用Node.js和PostgreSQL构建数据库应用》PostgreSQL是一个功能强大的开源关系型数据库,而Node.js是构建高效网络应用的理想平台,结合这两个技术,我们可以创建出色的数据驱动... 目录初始化项目与安装依赖建立数据库连接执行CRUD操作查询数据插入数据更新数据删除数据完整示例与最佳

JDK8(Java Development kit)的安装与配置全过程

《JDK8(JavaDevelopmentkit)的安装与配置全过程》文章简要介绍了Java的核心特点(如跨平台、JVM机制)及JDK/JRE的区别,重点讲解了如何通过配置环境变量(PATH和JA... 目录Java特点JDKJREJDK的下载,安装配置环境变量总结Java特点说起 Java,大家肯定都

使用Go调用第三方API的方法详解

《使用Go调用第三方API的方法详解》在现代应用开发中,调用第三方API是非常常见的场景,比如获取天气预报、翻译文本、发送短信等,Go作为一门高效并发的编程语言,拥有强大的标准库和丰富的第三方库,可以... 目录引言一、准备工作二、案例1:调用天气查询 API1. 注册并获取 API Key2. 代码实现3

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

在Android中使用WebView在线查看PDF文件的方法示例

《在Android中使用WebView在线查看PDF文件的方法示例》在Android应用开发中,有时我们需要在客户端展示PDF文件,以便用户可以阅读或交互,:本文主要介绍在Android中使用We... 目录简介:1. WebView组件介绍2. 在androidManifest.XML中添加Interne