在Android7.0上,使用下面的代码进行跳转到apk安装的页面
final File file = new File(filePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data = Uri.fromFile(file);
intent.setDataAndType(data, "application/vnd.android.package-archive");
context.startActivity(intent);
会抛出下面的异常FileUriExposedException
android.os.FileUriExposedException: “你的项目升级下载的apk的存放的地址”exposed beyond app through Intent.getData()
是因为随着Android版本的升级,对用户的数据的保护越来越高。
同时,Android提供了FileProvider来实现app间的数据共享。
解决方法
1、声明一个FileProvider
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="你的包名">
<application
...>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="你的包名+.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
...
</application>
</manifest>
参数 | 说明 | 备注 |
---|---|---|
name | FileProvider组件的完整类名 | android.support.v4.content.FileProvider |
authorities | 域名 | 为了保证唯一性,最好使用包名+fileprovider |
grantUriPermissions | 是否允许你可以对文件授予临时权限 | true |
exported | 是否需要暴露它 | false |
2、添加file_paths.xml文件
在res/xml的路径下创建file_paths.xml的文件,文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="name" path="path" />
<cache-path name="name" path="path" />
<external-path name="name" path="path" />
<external-files-path name="name" path="path" />
<external-cache-path name="name" path="path" />
</paths>
//name=随便的命名,没特殊要求。path=该路径的具体的文件内容,如果是全部的文件就填写path="."
参数 | 说明 |
---|---|
files-path | 对应的是Context.getFilesDir,返回的是/data/data/“你的项目名称”/files |
cache-path | 对应的是getCacheDir,返回的是/data/data/“你的项目名称”/cache |
external-path | 对应的是Environment.getExternalStorageDirectory,返回的是/storage/emulated/0 |
external-files-path | 对应的是Context.getExternalFilesDir(null)返回的是/storage/emulated/0/Android/data/“你的项目名称”/files |
external-cache-path | 对应的是Context.getExternalFilesDir(null)返回的是/storage/emulated/0/Android/data/“你的项目名称”/cache |
3、installapk的代码改成
final File file = new File(filePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
data = FileProvider.getUriForFile(mApp,"声明fileprovider时的android:authorities",file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}else {
data = Uri.fromFile(file);
}
//不添加这个会抛出Caused by: android.util.AndroidRuntimeException:
//Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag.
//Is this really what you want?
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
intent.setDataAndType(data, "application/vnd.android.package-archive");
context.startActivity(intent);
4、添加请求安装app的权限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
5、最后有的机型可能需要再打开外部的来源的安装。