问题

通过startActivity去对外打开、分享数据时出现

android.os.FileUriExposedException: file:///storage/emulated/0/xxx exposed beyond app through Intent.getData()        at android.os.StrictMode.onFileUriExposed(StrictMode.java:1960)        at android.net.Uri.checkFileUriExposed(Uri.java:2356)        at android.content.Intent.prepareToLeaveProcess(Intent.java:9898)        at android.content.Intent.prepareToLeaveProcess(Intent.java:9850)        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1612)        at android.app.Activity.startActivityForResult(Activity.java:4555)        at android.app.Activity.startActivityForResult(Activity.java:4513)        at android.app.Activity.startActivity(Activity.java:4874)        at android.app.Activity.startActivity(Activity.java:4842)

这种问题对于适配过Android 7调用系统安装器覆盖安装的开发者来说不陌生。

如安装类的场景

Intent intent = new Intent();intent.setAction(Intent.ACTION_VIEW);intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");startActivity(intent);

文档打开的场景

Intent intent = new Intent(Intent.ACTION_VIEW);  intent.setDataAndType(Uri.fromFile(file), "application/pdf");  intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);  startActivity(intent);  

原因分析

在应用间共享文件
对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在您的应用外部公开 file:// URI。如果一项包含文件 URI 的 intent 离开您的应用,则应用出现故障,并出现 FileUriExposedException 异常。

要在应用间共享文件,您应发送一项 content:// URI,并授予 URI 临时访问权限。也就是说,对于应用间共享文件这块,Android N中做了强制性要求

解决方法

方法一

如果对targetSdkVersion没有明确要求,可以将targetSdkVersion降低到24以下,如果targetSdkVersion 23,则不存在以上问题

方法二

使用FileProvider进行解决

FileProvider使用大概分为以下几个步骤:

  1. manifest中申明FileProvider
  2. res/xml中定义对外暴露的文件夹路径
  3. 生成content://类型的Uri
  4. 给Uri授予临时权限
  5. 使用Intent传递Uri

1. manifest中申明FileProvider:

  ...      ...                    ...  

AndroidX第一行应变为

androidx.core.content.FileProvider

android:name:provider你可以使用v4包提供的FileProvider,或者自定义的,只需要在name申明就好了,一般使用系统的就足够了。

android:authorities:类似schema,命名空间之类,后面会用到。

android:exported:false表示我们的provider不需要对外开放。

android:grantUriPermissions:申明为true,你才能获取临时共享权限。

2. res/xml中定义对外暴露的文件夹路径:

新建filepaths.xml,文件名随便起,后面会引用到。

    

paths里面的界面分别代表:

  • 代表context.getFileDir()
  • 代表context.getCacheDir()
  • 代表Environment.getExternalStorageDirectory()
  • 代表context.getExternalFilesDirs()
  • 代表context.getExternalCacheDirs()

path="/."表示的是当前目录下的所有目录。
注意:如果你选择吧这些选项全部都加到资源文件中,那么这些条目的name属性值要互不相同。
声明之后,代码中就可以使用所声明的当前文件夹以及其子文件夹。

3. 使用FileProvider

如安装代码:

Intent intent = new Intent(Intent.ACTION_VIEW);File apkFile = new File(apkSavePath);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);    Uri uri = FileProvider.getUriForFile(getActivity(), getActivity().getPackageName() + ".fileprovider", apkFile);    intent.setDataAndType(uri, "application/vnd.android.package-archive");} else {    intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");}startActivity(intent);

参考引用

https://blog.csdn.net/namehybin/article/details/78571964

https://blog.csdn.net/u010356768/article/details/89212742

更多相关文章

  1. android
  2. 总结系列-Android的文件系统
  3. [Android] Android(安卓)使用 Greendao 操作 db sqlite(1)-- 直
  4. android webview 使用
  5. 【android】shape的使用
  6. ToolBar的使用
  7. Android避免启动时闪一下黑屏
  8. Android技术文章收集
  9. 【Android】PA4D_CH6 使用Internat资源

随机推荐

  1. android 将Json数据动态的添加到String[]
  2. Android(安卓)ListView两种长按弹出菜单
  3. Android使用MediaCodec将摄像头采集的视
  4. TabHost 和 FragmentTabHost
  5. 初学Android,开发自定义的View(四)
  6. android MIT App Inventor 2 Beta 中文资
  7. Android中解析Json方法
  8. Android——Video/视频 相关知识总结贴
  9. Android打造炫酷进度条效果
  10. android开发数据储存的路径示例