道客优

1234
Android7.0 无法打开相机
2019-03-01 刀刻油 阅读:1304

Android7.0以上调用相机,有些手机会出现如下异常

android.os.FileUriExposedException: file:///storage/emulated/0/ exposed beyond app through ClipData.Item.getUri()
    at android.os.StrictMode.onFileUriExposed(StrictMode.java:1975)
    at android.net.Uri.checkFileUriExposed(Uri.java:2355)
    at android.content.ClipData.prepareToLeaveProcess(ClipData.java:941)
    at android.content.Intent.prepareToLeaveProcess(Intent.java:9944)
    at android.content.Intent.prepareToLeaveProcess(Intent.java:9929)
    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1622)

调用相机代码如下


Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));  

intent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);  

startActivityForResult(intent, REQ_TAKE);

网上有人说在Application中添加如下

StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
builder.detectFileUriExposure();

加完后发现不起作用。

7.0 调用系统相机拍照不再允许使用Uri方式,应该替换为FileProvider
解决办法如下:
  在AndroidManifest里添加provider          
  <!-- 解决 Android N 7.0 上 报错:android.os.FileUriExposedException -->             
  <provider                 
      android:name="android.support.v4.content.FileProvider"                 
      android:authorities="这里写包名.fileProvider"                 
      android:exported="false"                 
      android:grantUriPermissions="true"                 
      tools:replace="android:authorities">                 
      <meta-data                     
      android:name="android.support.FILE_PROVIDER_PATHS"                     
      android:resource="@xml/file_paths"/>             
  </provider> 
  同时需要在res下的xml包下新建一个 file_paths.xml 文件,里面是这样的:     
  <?xml version="1.0" encoding="utf-8"?>     
  <paths>         
      <!--<external-path path="Android/data/com.chemao.certification/" 
      name="files_root" />-->         
      <external-path             
      name="img"             
      path="myapp/img"/>     
  </paths> 
  file_path.xml里的标签用法如下

1.files-path

<files-path name="name" path="path" />

代表与Context.getFileDir()相同的文件路径

2.cache-path

<cache-path name="name" path="path" />

代表与getCacheDir()相同的文件路径

3.external-path

<external-path name="name" path="path" />

代表与Environment.getExternalStorageDirectory()相同的文件路径

4.external-files-path

<external-files-path name="name" path="path" />

代表与Context#getExternalFilesDir(String) 和Context.getExternalFilesDir(null)相同的文件路径

5.external-cache-path

<external-cache-path name="name" path="path" />

代表与Context.getExternalCacheDir()相同的文件路径

调用相机处代码

int currentapiVersion = android.os.Build.VERSION.SDK_INT; 
if (currentapiVersion< Build.VERSION_CODES.N){        
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(getUserDir(), )));  
startActivityForResult(intent, TAKE_PHOTO);  
}  else{                 
File dir = new File(getDir() + "/img");  
File file = new File(dir,”photo”);  
String packageName = Application.getPackageName();  
Uri imageUri = FileProvider.getUriForFile(activity, packageName + ".fileprovider", file);  
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);  
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);  
startActivityForResult(intent, PHOTO);  
}

注意这里的file一定要写res下path中的external-path

推荐阅读: