web-dev-qa-db-ja.com

Android SDKのカメラインテントFileUriExposedException> = 24

このコードを使用して、カメラから画像を取得し、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() {

                }
            });
        }
    }
}

マシュマロでは大丈夫ですが、ヌガーではこのエラーが発生しました:

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)

どうすればこのエラーを解決できますか?ソリューションを検索しましたが、誰も動作しません。

ありがとう

13
ste9206

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

そして、provider_paths.xml resフォルダの下の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>

詳細: 記事全体

32

以下のように簡単にできます。これらの2行をアクティビティのonCreateに配置します。

StrictMode.VmPolicy.Builder newbuilder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(newbuilder.build());

URIの公開はVmによって無視されます。私の問題を解決しました。

16
deva11