when take photo get - java.lang.Throwable: file:// Uri exposed through ClipData.Item.getUri()

Michael picture Michael · Sep 17, 2015 · Viewed 19k times · Source

The Exception is:

file:// Uri exposed through ClipData.Item.getUri()
java.lang.Throwable: file:// Uri exposed through ClipData.Item.getUri()
    at android.os.StrictMode.onFileUriExposed(StrictMode.java:1618)
    at android.net.Uri.checkFileUriExposed(Uri.java:2341)
    at android.content.ClipData.prepareToLeaveProcess(ClipData.java:808)
    at android.content.Intent.prepareToLeaveProcess(Intent.java:7926)
    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1506)
    at android.app.Activity.startActivityForResult(Activity.java:3832)
    at android.app.Activity.startActivityForResult(Activity.java:3783)
    at android.support.v4.app.FragmentActivity.startActivityFromFragment(Unknown Source)
    at android.support.v4.app.Fragment.startActivityForResult(Unknown Source)
    at me.chunyu.ChunyuDoctor.Utility.w.takePhoto(Unknown Source)
    at me.chunyu.ChunyuDoctor.Dialog.ChoosePhotoDialogFragment.takePhoto(Unknown Source)
    at me.chunyu.ChunyuDoctor.Dialog.ChoosePhotoDialogFragment.access$000(Unknown Source)
    at me.chunyu.ChunyuDoctor.Dialog.b.onClick(Unknown Source)
    at me.chunyu.ChunyuDoctor.Dialog.ChoiceDialogFragment.onClick(Unknown Source)
    at android.view.View.performClick(View.java:4848)
    at android.view.View$PerformClick.run(View.java:20270)
    at android.os.Handler.handleCallback(Handler.java:815)
    at android.os.Handler.dispatchMessage(Handler.java:104)
    at android.os.Looper.loop(Looper.java:194)
    at android.app.ActivityThread.main(ActivityThread.java:5643)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:960)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

My code is here:

public static void takePhoto(Fragment fragment, int token, Uri uri) {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (uri != null) {
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
    }
    fragment.startActivityForResult(intent, token);
}

I searched the similar problems and solutions. And modify the code as follow:

public static void takePhoto(Fragment fragment, int token, Uri uri) {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    if (uri != null) {
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
    }
    fragment.startActivityForResult(intent, token);
}

But it is also not work.

It happend on Android 5.1 While work well on Android 4.3. Is there anyone meet the same problem? Ask for some advance. Waiting online...

Answer

Michael picture Michael · Sep 22, 2015

I have already resolved this problem.

First, this problem occurred because StrictMode prevents passing URIs with a file:// scheme.

So there are two solutions:

  1. Change StrictMode. See similar problem and its code. But for our apps, it is not realistic to modify the Android source code.

  2. Use another URI scheme, instead of file://. For example, content:// related to MediaStore.

So I chose the second method:

private void doTakePhoto() {
    try {
        ContentValues values = new ContentValues(1);
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
        mCameraTempUri = getActivity().getContentResolver()
                .insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

        takePhoto(this, RequestCode.REQCODE_TAKE_PHOTO, mCameraTempUri);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void takePhoto(Fragment fragment, int token, Uri uri) {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
        | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    if (uri != null) {
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
    }
    fragment.startActivityForResult(intent, token);
}

Also, there is another solution.