ClipData.Item.getUri के माध्यम से ऐप से परे उजागर


99

एंड्रॉइड फाइल सिस्टम में जोड़े गए नए फीचर के बाद मैं एक समस्या को ठीक करने की कोशिश कर रहा हूं, लेकिन मुझे यह त्रुटि मिली:

android.os.FileUriExposedException: file:///storage/emulated/0/MyApp/Camera_20180105_172234.jpg exposed beyond app through ClipData.Item.getUri()

इसलिए मुझे उम्मीद है कि कोई मुझे इसे ठीक करने में मदद कर सकता है :)

धन्यवाद

private Uri getTempUri() {
    // Create an image file name
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
    String dt = sdf.format(new Date());
    imageFile = null;
    imageFile = new File(Environment.getExternalStorageDirectory()
            + "/MyApp/", "Camera_" + dt + ".jpg");
    AppLog.Log(
            TAG,
            "New Camera Image Path:- "
                    + Environment.getExternalStorageDirectory()
                    + "/MyApp/" + "Camera_" + dt + ".jpg");
    File file = new File(Environment.getExternalStorageDirectory() + "/MyApp");
    if (!file.exists()) {
        file.mkdir();
    }
    imagePath = Environment.getExternalStorageDirectory() + "/MyApp/"
            + "Camera_" + dt + ".jpg";
    imageUri = Uri.fromFile(imageFile);
    return imageUri;
}

जवाबों:


169

Sdk 24 और ऊपर के लिए, यदि आपको अपने ऐप स्टोरेज के बाहर किसी फ़ाइल की उरई प्राप्त करने की आवश्यकता है तो आपके पास यह त्रुटि है।
@ eranda.del समाधान आपको इसे अनुमति देने के लिए नीति को बदलने देता है और यह ठीक काम करता है।

हालाँकि यदि आप अपने ऐप की एपीआई नीति को बदलने के लिए Google दिशानिर्देश का पालन करना चाहते हैं, तो आपको एक फ़ाइलप्रोइडर का उपयोग करना होगा।

फ़ाइल का URI प्राप्त करने के लिए सबसे पहले आपको FileProvider.getUriForFile () विधि का उपयोग करना होगा:

Uri imageUri = FileProvider.getUriForFile(
            MainActivity.this,
            "com.example.homefolder.example.provider", //(use your app signature + ".provider" )
            imageFile);

फिर आपको अपने प्रदाता को अपने एंड्रॉइड मैनिफ़ेस्ट में कॉन्फ़िगर करना होगा:

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

("अधिकारियों" में getUriForFile () विधि (एप्लिकेशन हस्ताक्षर + ".provider") के दूसरे तर्क की तुलना में समान मूल्य का उपयोग करें।

और अंत में आपको ressources फ़ाइल बनाने की आवश्यकता है: "file_paths"। इस फ़ाइल को 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>

79
"डेवलपर्स जीवन को आसान बनाएं" - यह हर नए एपीआई, सही Google के लिए टैगलाइन है?
किरिल कर्मज़ीन

12
ब्रेंडन द्वारा प्रदान किया गया समाधान सही है लेकिन यह कॉपी-पेस्ट तैयार नहीं है, आपको यह जांचने की आवश्यकता है कि क्या यह आपकी आवश्यकताओं के अनुरूप है। <external-path ...का उपयोग तब किया जाता है जब आप एनवायरनमेंट .getExternalStorageDirectory () चाहते हैं। और <files-path ...यदि आपको Context.getFilesDir () की आवश्यकता है, का उपयोग करें । आप सबसे पहले आधिकारिक डॉक्स की बेहतर जांच करते हैं: developer.android.com/reference/android/support/v4/content/…
किरिल कर्मज़ीन

9
एक अनुस्मारक यदि आप androidx (नया समर्थन नाम स्थान) का उपयोग कर रहे हैं, तो आप यहाँ ( डेवलपर .android.com/reference/androidx/core/content/… ) उचित दस्तावेज़ पा सकते हैं ।
रॉड्रिरोक

20
ध्यान दें कि androidxइसमें है:android:name="androidx.core.content.FileProvider"
smörkex

150

प्रारंभ कैमरा या फ़ाइल ब्राउज़िंग से पहले निम्नलिखित कोड ब्लॉक जोड़ें

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

कृपया रेफरल लिंक को सख्त मोड में देखें और इसके उपयोग और तकनीकी विवरणों के बारे में बताया।


24
इसे हल करने का सही तरीका नहीं है, यह मूल रूप से सख्त नीतियों को हटा देगा। और सुरक्षा चेतावनी की अनदेखी करेगा
अहसान जहीर

इस पर कुछ पेशेवरों और विपक्ष हैं। कृपया अधिक जानकारी पाने के लिए कृपया निम्नलिखित देखें stackoverflow.com/questions/18100161/…
eranda.del

यह काम करता है, अगर कोई ड्रा बैक है तो कृपया मुझे बताएं :)
हनान

कोड ने मेरे लिए अपवाद को हल कर दिया। हालांकि, यहां शीर्ष टिप्पणी कहती है कि कोड इसे हल करने का सही तरीका नहीं है। क्या किसी को पता है कि तब उचित तरीका क्या होगा?
22

Google प्रोग्रामर्स से नफरत करता है।
जौबर्ट वास्कोनसेलोस

0

कोई आवश्यक प्रदाता AndroidManifest केवल कैमरा और संग्रहण की अनुमति में विन्यास की अनुमति दी जानी चाहिए। कैमरा शुरू करने के लिए निम्नलिखित कोड का उपयोग करें:

final int REQUEST_ACTION_CAMERA = 9;
void openCamra() {
Intent cameraImgIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

cameraImgIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID +".provider",
                new File("your_file_name_with_dir")));
startActivityForResult(cameraImgIntent, REQUEST_ACTION_CAMERA);
}

छवि कैप्चर करने के बाद, आप अपनी कैप्चर की गई छवि को देख सकते हैं:

"your_file_name_with_dir"

AndroidManifest में प्रदाता के कॉन्फ़िगरेशन की व्याख्या करना बेहतर है, अन्य कोड देने से।
रोष
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.