最近刚刚把古老的项目targetSdk版本升级到26,升级之前是19(非常非常古老了)。那么升级后一些问题开始出现。
Android 8.0 (Android O)为了针对一些流氓软件引导用户安装其他无关应用。在应用权限设置的“特殊访问权限”中,加入了“安装其他应用”的设置,默认是关闭的。所以安装时需要授权用户去开启。
实现
1.清单文件权限声明
|
1 |
|
2.点击安装判断是否有权限

1 if (Build.VERSION.SDK_INT >= 26) {
2 //来判断应用是否有权限安装apk
3 boolean installAllowed= getPackageManager().canRequestPackageInstalls();
4 //有权限
5 if (installAllowed) {
6 //安装apk
7 install(apkPath);
8 } else {
9 //无权限 申请权限
10 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, INSTALL_APK_REQUESTCODE);
11 }
12 } else {
13 install(apkPath);
14 }

权限申请回调

1 @Override
2 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
3 super.onRequestPermissionsResult(requestCode, permissions, grantResults);
4 switch (requestCode) {
5 case INSTALL_APK_REQUESTCODE:
6 //有注册权限且用户允许安装
7 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
8 install(apkPath);
9 } else {
10 //将用户引导至安装未知应用界面。
11 Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
12 startActivityForResult(intent, GET_UNKNOWN_APP_SOURCES);
13 }
14 break;
15 }
16 }

安装APK

1 private void install(String apkPath) {
2 //7.0以上通过FileProvider
3 if (Environment.SYSTEM_VERSION_CODE >= 24) {
4 Uri uri = FileProvider.getUriForFile(context, Environment.FILE_PROVIDER_AUTHORITY, new File(apkPath));
5 Intent intent = new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "application/vnd.android.package-archive");
6 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
8 context.startActivity(intent);
9 } else {
10 Intent intent = new Intent(Intent.ACTION_VIEW);
11 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
12 intent.setDataAndType(Uri.parse("file://" + apkPath), "application/vnd.android.package-archive");
13 context.startActivity(intent);
14 }
15 }

这里需要注意的是7.0引入了“私有目录被限制访问”,“StrictMode API 政策”。” StrictMode API 政策” 是指禁止向你的应用外公开 file:// URI。 如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,应用失败,并出现 FileUriExposedException 异常。
上面用到的代码中的Uri.fromFile 其实就是生成一个file://URL。一旦我们通过这种办法打开其它程序(这里打开系统包安装器)就认为file:// URI类型的 Intent 离开你的应用。这样程序就会发生异常。
解决办法:
用FileProvider来解决这一问题,首先在清单文件中添加:

1 <!-- FileProvider配置访问路径,适配7.0及其以上-->
2 <provider
3 android:name="android.support.v4.content.FileProvider"
4 android:authorities="${applicationId}.provider"
5 android:exported="false"
6 android:grantUriPermissions="true">
7 <meta-data
8 android:name="android.support.FILE_PROVIDER_PATHS"
9 android:resource="@xml/provider_paths" />
10 </provider>

authorities:app的包名;fileProvider grantUriPermissions:true;表示授予 URI 临时访问权限 exported:false ; resource:下一步添加的文件。
然后在res下新建一个名为xml的文件家,再新建文件provider_paths:

1 <?xml version="1.0" encoding="utf-8"?> 2 <paths> 3 <external-path 4 name="files_root" 5 path="Android/data/com.example.downloadapk/"/> 6 <external-path 7 name="external_storage_root" 8 path="."/> 9 </paths>

path:需要临时授权访问的路径(.代表所有路径) name:给访问路径命名。
这样就可以完美解决7.0和8.0的问题啦!
博客详细介绍了如何在Android 8.0及以上版本处理权限升级带来的问题,包括如何请求安装其他应用的权限,使用FileProvider解决7.0以上版本的文件访问限制,以及如何处理安装APK的流程。同时,提供了相应的代码示例,帮助开发者解决在新版本Android中遇到的安装应用权限和文件访问权限的问题。
992

被折叠的 条评论
为什么被折叠?



