2015-09-17 8 views
22

अपवाद है:जब ले तस्वीर मिल - java.lang.Throwable: file: // उरी ClipData.Item.getUri() के माध्यम से अवगत कराया

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) 

मेरे कोड यहाँ है:

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

मैंने इसी तरह की समस्याओं और समाधानों की खोज की। और इस प्रकार कोड को संशोधित:

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

लेकिन यह भी काम नहीं कर रहा है।

यह एंड्रॉइड 4.3 पर अच्छा काम करता है जबकि एंड्रॉइड 4.3 पर अच्छा काम करता है। क्या कोई भी एक ही समस्या से मिल रहा है? कुछ अग्रिम के लिए पूछें। ऑनलाइन प्रतीक्षा कर रहा है ...

उत्तर

15

मैंने पहले से ही इस समस्या का समाधान किया है।

सबसे पहले, यह समस्या आई क्योंकि StrictModefile:// योजना के साथ यूआरआई पास करने से रोकता है।

  1. बदलें StrictMode:

    तो दो समाधान हैं। similar problem और its code देखें। लेकिन हमारे ऐप्स के लिए, एंड्रॉइड स्रोत कोड को संशोधित करना यथार्थवादी नहीं है।

  2. file:// के बजाय, एक और यूआरआई योजना का उपयोग करें। उदाहरण के लिए, MediaStore से संबंधित है।

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

    इसके अलावा, वहाँ है एक और solution:

तो मैं दूसरी विधि चुना है।

+0

"... android.permission.WRITE_EXTERNAL_STORAGE, या grantUriPermission की आवश्यकता है()" –

5

इस त्रुटि का कारण यह है कि फ़ाइल: // uri योजना अब और समर्थित नहीं है क्योंकि सुरक्षा का खुलासा किया गया है। https://code.google.com/p/android/issues/detail?id=203555

और हम लक्ष्य का उपयोग नहीं कर सकते हैं: // uri लक्ष्य एसडीके 'एन' के साथ और भी बाद में। https://commonsware.com/blog/2016/03/14/psa-file-scheme-ban-n-developer-preview.html

तो, जवाब सही है। फ़ाइल का उपयोग करने वाले किसी भी व्यक्ति ने // // स्थानीय फाइलों के प्रकार प्रदान करने के लिए सामग्री बदल दी है।

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

सूचना वहाँ एक नोट गूगल एक बनाने के लिए कहा गया है कि कि "सामग्री: //"

+1

धन्यवाद, मैं 'targetSdk' डाउनग्रेड करने के लिए ** 23 ** और यह काम कर रहा शुरू कर दिया है। मेरा मतलब है 'File.getUriFrom (फ़ाइल फ़ाइल) ' – murt

10

तो, मैं वास्तव में इस बारे में पढ़ रहा था, और यह इस संभाल करने के लिए सही समाधान लगता है पीछा कर रहा है "फ़ाइल: //" आधारित संसाधन के बजाय फ़ाइल करें।,

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.

इसके अलावा, आप निम्नलिखित सेटअप करने की आवश्यकता होगी:

यह गूगल से है 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> 

नोट: (गूगल की साइट से लिया) 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> 

आप अधिक जानकारी चाहते हैं, तो यहाँ तक पढ़ https://developer.android.com/training/camera/photobasics.html

3

सारांश में: file: // योजना अब targetSdkVersion 24 (एंड्रॉयड नूगा)

आप के लिए है पर आशय के साथ संलग्न किए जाने की अनुमति नहीं है यदि आप एपीआई 24 + दो लिंक समर्थन करने की योजना अपने कोड में परिवर्तित करें: https://developer.android.com/training/camera/photobasics.html https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en

+0

अच्छा, यह वास्तव में सहायक है –

3

समाधान FileProvider का उपयोग कर के अलावा, वहाँ एक और तरीका है इस को हल करने के लिए है। बस application.onCreate() विधि में डाल दिया। इस तरह वीएम फ़ाइल यूआरआई एक्सपोजर को अनदेखा करता है।

StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); 
StrictMode.setVmPolicy(builder.build()); 
संबंधित मुद्दे