Android N及以上版本应用安装包下载完成自动弹出安装界面的适配方法
在实现下载和安装APP功能的时候在Android较高版本可能会遇到如下的问题:
- 安装Apk时报错:android.os.FileUriExposedException: file:///storage/emulated/0/Download/*.apk exposed beyond app through Intent.getData();
- 弹不出安装界面。
上面遇到的这两个问题主要是Android 8.0针对未知来源应用做了权限限制,针对该问题的解决及完整适配方法如下。
完整适配步骤
1、适配Android 8.0及以上系统,需要在AndroidManifest.xml中添加安装权限:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
Android O及Android 8.0及以上系统若不加该权限,会遇到跳转到安装界面时闪退的问题,原因是8.0针对未知来源应用,在应用权限设置的“特殊访问权限”中,加入了“安装其他应用”的设置。
2、在AndroidManifest.xml中添加provider声明:
<application
......
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
3、在res目录下新建一个名为xml的目录,并在xml目录下新建一个名为file_paths.xml的文件;
4、在file_paths.xml的文件中添加如下代码:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="external_files_path" path="Download" /><!--path:需要临时授权访问的路径(.代表所有路径)
name:就是你给这个访问路径起个名字-->
<!--为了适配所有路径可以设置 path = "." -->
<external-path path="." name="external_storage_root" />
</paths>
5、适配Android N弹出安装界面的代码:
private void isAPK(String filePath) {
File file = new File(filePath);
if (file.getName().endsWith(".apk")) {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 适配Android 7系统版本
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件
uri = FileProvider.getUriForFile(XRetrofitApp.getApplication(), XRetrofitApp.getApplication().getPackageName() + ".fileprovider", file);//通过FileProvider创建一个content类型的Uri
} else {
uri = Uri.fromFile(file);
}
intent.setDataAndType(uri, "application/vnd.android.package-archive"); // 对应apk类型
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
XRetrofitApp.getApplication().startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
PS:下载完文件,可以通过发送扫描广播,告诉系统扫描数据库及时刷新文档里面的文件,这样即使下载安装出错,还可以进入文档查看安装应用包,代码如下:
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
//根据需要自定义IMG_PATH路径
Uri uri = Uri.fromFile(new File(downLoadPath + java.io.File.separator));
intent.setData(uri);
context.sendBroadcast(intent);