1 分析Log
04-11 10:41:41.591 1302 1302 E AndroidRuntime: android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.android.mms/cache/.temp0.3gp exposed beyond app through Intent.getData()
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.os.StrictMode.onFileUriExposed(StrictMode.java:1960)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.net.Uri.checkFileUriExposed(Uri.java:2356)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.content.Intent.prepareToLeaveProcess(Intent.java:9881)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.content.Intent.prepareToLeaveProcess(Intent.java:9835)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1612)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4501)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4459)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at com.android.mms.ui.ComposeMessageActivity.startActivityForResult(ComposeMessageActivity.java:934)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.app.Activity.startActivity(Activity.java:4820)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.app.Activity.startActivity(Activity.java:4788)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at com.android.mms.ui.MessageUtils.viewSimpleSlideshow(MessageUtils.java:1224)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at com.android.mms.ui.ComposeMessageActivity.viewMmsMessageAttachment(ComposeMessageActivity.java:682)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at com.android.mms.ui.ComposeMessageActivity.-wrap68(Unknown Source:0)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at com.android.mms.ui.ComposeMessageActivity$1.handleMessage(ComposeMessageActivity.java:642)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.os.Looper.loop(Looper.java:164)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6518)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
04-11 10:41:41.591 1302 1302 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
04-11 10:41:41.603 1246 765 D ActivityTrigger: ActivityTrigger activityPauseTrigger
2 定位原因,经过查资料发现
android 8.0 的版本:当把targetSdkVersion指定成24及之上并且在API>=24的设备上运行时。这种方式则会出现FileUriExposedException异常
原因
Android 8.0的系统对权限的管理更加严格
不在让其他app可以访问另外一个apk的中把file://Uri(主要是权限问题,如文件是私有的,没有权限无法访问),通过过谷歌文档,google提供了FileProvider,发现通过Intent或ClipData 等方法可以规避。由于需要运行中的权限
如果接收访问app 的file://Uri没有申请READ_EXTERNAL_STORAGE权限,在查看文件会让APP 挂掉。
3 解决方法
1.在AndroidManifest中添加provider节点
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="apk 的包名"
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="apk的包名.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
</manifest>
2 2.在res的xml目录下创建provider_paths
<?xml version="1.0" encoding="utf-8"?>
<pathsxmlns:android="http://schemas.android.com/apk/res/android">
<external-path path="Android/data/app的包名/" name="files_root"
> </paths>
TIPS
如果要共享的文件在SD卡上可以这样写
<external-path name="external_files" path="."/>
或者在某个目录下可以这样写
<external-path path="images/" name="myimages"/>
3.修改代码(最重要的地方,定位出问题的代码位置)
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
Uri videoUri;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//申请权限
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//getUriForFile的第二个参数就是Manifest中的authorities
videoUri = FileProvider.getUriForFile(context,"apk的包名.FileProvider", file);}
else {
videoUri = Uri.fromFile(file);
}
intent.setDataAndType(videoUri,"video/*");
context.startActivity(intent);
4 搞定