2015-09-17 23 views
22

Die Ausnahme ist:wenn nehmen Foto bekommen - java.lang.Throwable: file: // Uri durch ClipData.Item.getUri ausgesetzt()

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) 

Mein Code ist hier:

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); 
} 

Ich suchte die ähnlichen Probleme und Lösungen. Und den Code wie folgt ändern:

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); 
} 

Aber es ist die Arbeit auch nicht.

Es passiert auf Android 5.1 Während der Arbeit gut auf Android 4.3. Gibt es jemanden, der das gleiche Problem hat? Fragen Sie nach etwas Fortschritt. Warten online ...

Antwort

15

Ich habe dieses Problem bereits gelöst.

Zuerst trat dieses Problem auf, weil StrictMode verhindert, URIs mit einem file://-Schema zu übergeben.

So gibt es zwei Lösungen:

  1. ändern StrictMode. Siehe similar problem und its code. Aber für unsere Apps ist es nicht realistisch, den Android-Quellcode zu ändern.

  2. Verwenden Sie ein anderes URI-Schema anstelle von file://. Zum Beispiel content:// bezogen auf MediaStore.

Also wählte ich die zweite Methode:

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); 
} 

Außerdem gibt es eine andere solution.

+0

"... erfordert android.permission.WRITE_EXTERNAL_STORAGE oder grantUriPermission()" –

5

Der Grund für diesen Fehler ist, dass Datei: // uri Schema nicht mehr unterstützt wird, da die Sicherheit ausgesetzt ist. https://code.google.com/p/android/issues/detail?id=203555

Und wir können file: // uri nicht mehr mit targetSDK 'N' verwenden. https://commonsware.com/blog/2016/03/14/psa-file-scheme-ban-n-developer-preview.html

Also, die Antwort ist richtig. Jeder, der file: // verwendet, hat change content: //, um Arten von lokalen Dateien bereitzustellen.

+1

Dank stufte I 'targetSdk' bis ** 23 ** und es hat begonnen zu arbeiten. Ich meine 'File.getUriFrom (Datei-Datei)' – murt

10

Also, ich war eigentlich darüber zu lesen, und es scheint, die richtige Lösung zu handhaben ist die folgende:

String mCurrentPhotoPath; 

private File createImageFile() throws IOException { 
    // Create an image file name 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
    String imageFileName = "JPEG_" + timeStamp + "_"; 
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); 
    File image = File.createTempFile(
     imageFileName, /* prefix */ 
     ".jpg",   /* suffix */ 
     storageDir  /* directory */ 
    ); 

    // Save a file: path for use with ACTION_VIEW intents 
    mCurrentPhotoPath = "file:" + image.getAbsolutePath(); 
    return image; 
} 

static final int REQUEST_TAKE_PHOTO = 1; 

private void dispatchTakePictureIntent() { 
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
    // Ensure that there's a camera activity to handle the intent 
    if (takePictureIntent.resolveActivity(getPackageManager()) != null) { 
     // Create the File where the photo should go 
     File photoFile = null; 
     try { 
      photoFile = createImageFile(); 
     } catch (IOException ex) { 
      // Error occurred while creating the File 
      ... 
     } 
     // Continue only if the File was successfully created 
     if (photoFile != null) { 
      Uri photoURI = FileProvider.getUriForFile(this, 
                "com.example.android.fileprovider", 
                photoFile); 
      takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); 
      startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO); 
     } 
    } 
} 

Hinweis gibt es eine Notiz, dass Google sagt, eine „Inhalt: //“ Datei anstelle einer "Datei: //" basierten Ressource. Now, you need to configure the FileProvider. In your app's manifest, add a provider to your application:

<application> 
    ... 
    <provider 
     android:name="android.support.v4.content.FileProvider" 
     android:authorities="com.example.android.fileprovider" 
     android:exported="false" 
     android:grantUriPermissions="true"> 
     <meta-data 
      android:name="android.support.FILE_PROVIDER_PATHS" 
      android:resource="@xml/file_paths"></meta-data> 
    </provider> 
    ... 
</application> 

Hinweis:

Dies ist von Google: die folgenden

Note: We are using getUriForFile(Context, String, File) which returns a content:// URI. For more recent apps targeting Android N and higher, passing a file:// URI across a package boundary causes a FileUriExposedException. Therefore, we now present a more generic way of storing images using a FileProvider.

Auch Sie Setup benötigen (Entnommen aus Googles Website) Make sure that the authorities string matches the second argument to getUriForFile(Context, String, File). In the meta-data section of the provider definition, you can see that the provider expects eligible paths to be configured in a dedicated resource file, res/xml/file_paths.xml. Here is the content required for this particular example:

<?xml version="1.0" encoding="utf-8"?> 
<paths xmlns:android="http://schemas.android.com/apk/res/android"> 
    <external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" /> 
</paths> 

Wenn Sie weitere Informationen erhalten möchten: lesen Sie hier https://developer.android.com/training/camera/photobasics.html

3

Neben der Lösung der FileProvider verwendet wird, ist es eine andere Möglichkeit, dies zu umgehen. Einfach die Application.onCreate() -Methode einfügen. Auf diese Weise ignoriert die VM die Datei-URI-Belichtung.

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