Android 相机意图 FileUriExposedException for SDK >= 24
Posted
技术标签:
【中文标题】Android 相机意图 FileUriExposedException for SDK >= 24【英文标题】:Android camera intent FileUriExposedException for SDK >= 24 【发布时间】:2017-04-29 22:03:08 【问题描述】:我使用此代码从相机获取图片并将其放在 imageview 上:
private void openCamera()
mMediaUri =getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
Intent photoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
photoIntent.putExtra(MediaStore.EXTRA_OUTPUT, mMediaUri);
startActivityForResult(photoIntent, REQUEST_TAKE_PHOTO);
// dialog.dismiss();
private Uri getOutputMediaFileUri(int mediaTypeImage)
//check for external storage
if(isExternalStorageAvaiable())
File mediaStorageDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
String fileName = "";
String fileType = "";
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new java.util.Date());
fileName = "IMG_"+timeStamp;
fileType = ".jpg";
File mediaFile;
try
mediaFile = File.createTempFile(fileName,fileType,mediaStorageDir);
Log.i("st","File: "+Uri.fromFile(mediaFile));
catch (IOException e)
e.printStackTrace();
Log.i("St","Error creating file: " + mediaStorageDir.getAbsolutePath() +fileName +fileType);
return null;
return Uri.fromFile(mediaFile);
//something went wrong
return null;
private boolean isExternalStorageAvaiable()
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state))
return true;
else
return false;
public void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == DIALOG_CODE)
String s = data.getStringExtra("choose");
if(s.equals(getString(R.string.takephoto)))
openCamera();
else if(s.equals(getString(R.string.library)))
// openGallery();
else if(resultCode == RESULT_OK)
if (requestCode == REQUEST_TAKE_PHOTO || requestCode == REQUEST_PICK_PHOTO) //dalla fotocamera
if (data != null) //caso galleria
mMediaUri = data.getData();
Picasso.with(getActivity()).load(mMediaUri).resize(1280, 1280).centerCrop().into(photo, new Callback()
public void onSuccess()
@Override
public void onError()
);
在 Marshmallow 中可以正常工作,但在 Nougat 中出现此错误:
E/androidRuntime: FATAL EXCEPTION: main
PID: 15471
android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/com.plen.myapp/files/Pictures/IMG_20161214_1516561294620205.jpg exposed beyond app through ClipData.Item.getUri()
at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
at android.net.Uri.checkFileUriExposed(Uri.java:2346)
at android.content.ClipData.prepareToLeaveProcess(ClipData.java:832)
at android.content.Intent.prepareToLeaveProcess(Intent.java:8925)
at android.content.Intent.prepareToLeaveProcess(Intent.java:8910)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1519)
at android.app.Activity.startActivityForResult(Activity.java:4224)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:48)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:77)
at android.support.v4.app.ActivityCompatJB.startActivityForResult(ActivityCompatJB.java:26)
at android.support.v4.app.ActivityCompat.startActivityForResult(ActivityCompat.java:146)
at android.support.v4.app.FragmentActivity.startActivityFromFragment(FragmentActivity.java:937)
at android.support.v4.app.FragmentActivity$HostCallbacks.onStartActivityFromFragment(FragmentActivity.java:1046)
at android.support.v4.app.Fragment.startActivityForResult(Fragment.java:956)
at android.support.v4.app.Fragment.startActivityForResult(Fragment.java:945)
at com.plen.myapp.MyAircrafts.AddAircraftFirstPartFragment.openCamera(AddAircraftFirstPartFragment.java:263)
at com.plen.myapp.MyAircrafts.AddAircraftFirstPartFragment.askReadStorage(AddAircraftFirstPartFragment.java:338)
at com.plen.myapp.MyAircrafts.AddAircraftFirstPartFragment.askWriteStorage(AddAircraftFirstPartFragment.java:355)
at com.plen.myapp.MyAircrafts.AddAircraftFirstPartFragment.loadNewPhoto(AddAircraftFirstPartFragment.java:159)
at com.plen.myapp.MyAircrafts.AddAircraftFirstPartFragment.access$000(AddAircraftFirstPartFragment.java:48)
at com.plen.myapp.MyAircrafts.AddAircraftFirstPartFragment$1.onClick(AddAircraftFirstPartFragment.java:75)
at android.view.View.performClick(View.java:5609)
at android.view.View$PerformClick.run(View.java:22266)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
我该如何解决这个错误?我已经搜索了解决方案,但没有一个有效。
谢谢
【问题讨论】:
***.com/questions/38200282/…(另见此示例项目:github.com/commonsguy/cw-omnibus/tree/master/Camera/…) @CommonsWare 但如果我使用它,它也适用于果冻豆?或者我需要为以前版本的 Android 使用其他代码? "但是如果我使用它,它也适用于 Jelly Bean?" -- 如果“this”是FileProvider
,则问题不在于Android OS版本,而在于用户的相机应用是否支持content
作为Uri
中Uri
的方案。有些会,有些不会。如果“this”是StrictMode
方法,那么所有版本的Android 都可以使用AFAIK,因为它会恢复FileUriExposedException
更改并允许您再次使用file
方案。
【参考方案1】:
代替return Uri.fromFile(mediaFile);
做
return FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
mediaFile);
这需要您将提供程序添加到AndroidManifest
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
<application
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="$applicationId.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
对于 AndroidX,请使用 androidx.core.content.FileProvider
然后在res文件夹下的xml文件夹中创建一个provider_paths.xml
文件。
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
阅读更多:Full article
【讨论】:
官方文档 - developer.android.com/training/secure-file-sharing/…【参考方案2】:它可以像下面这样简单地完成。 将这两行放在您的活动的 onCreate 中。
StrictMode.VmPolicy.Builder newbuilder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(newbuilder.build());
URI 暴露将被 Vm 忽略 我解决了我的问题。
【讨论】:
这似乎关闭了很多东西 它将完美运行。我没有发现任何新错误或此代码出现故障。 是的,你是对的。有用。看起来您正在安装一个未配置的策略对象。但它有效? 非常感谢。这对我有用。以上是关于Android 相机意图 FileUriExposedException for SDK >= 24的主要内容,如果未能解决你的问题,请参考以下文章