FileProvider दुर्घटना - एक शून्य स्ट्रिंग पर XmlResourceParser आह्वान करने का प्रयास


139

यह मेरी अभिव्यक्ति का एक हिस्सा है:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.asd"
    android:versionCode="118"
    android:versionName="118" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="19" />


    <application
        android:name="com.example.asd.AsdApplication"
        android:allowBackup="true"
        android:allowTaskReparenting="true"
        android:theme="@style/AsdTheme" >
        ...

        <provider
            android:name="com.example.asd.database.hq.ContentProviderDB"
            android:authorities="ourContentProviderAuthorities" >
        </provider>
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.asd.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>

       ...
    </application>

</manifest>

यह कच्चे / xml / filepaths.xml में फ़ाइलपथ फ़ाइल है

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="media"/>
</paths>

मैं इंटरनेट से एक वीडियो डाउनलोड करता हूं और इसे इस तरह आंतरिक भंडारण में सहेजता हूं:

public static boolean saveInputStreamToInternalStorageFile(Context context, String filename, byte[] dataToWrite, Context ctx) {
    FileOutputStream fos;
    try {
        fos = new FileOutputStream(context.getFilesDir() + File.separator + filename);

        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(dataToWrite);
        oos.close();
        return true;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        return false;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

मैं इसे इस तरह उपयोग करने की कोशिश करता हूं:

private void playVideoFromDeviceWithWorkaround(String fileName) {

    File newFile = new File(getFilesDir(), fileName);
    Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile);

    try {
        vvVideoFullscreen.setVideoURI(contentUri);
        showMediaControls = true;
        playVideo();
    } catch (Exception e) {
        playVideoFromNetwork();
    }

}

इस लाइन पर:

Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile); 

मुझे निम्नलिखित त्रुटि मिलती है:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:560)
at android.support.v4.content.FileProvider.getPathStrategy(FileProvider.java:534)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:376)

"यह फ़ाइलपथ फ़ाइल है" - आपकी परियोजना में वास्तव में यह फ़ाइल कहाँ है?
कॉमन्सवेयर

1
कच्चे / xml / filepaths.xml
जेके

2
अधिकारियों में मेरे पास .provider है, ऐप पैकेज में जोड़ा गया है, लेकिन जब getUriForFile पर कॉल किया जाता है, तो मुझे ऐपप्रोइडर नहीं चाहिए। शायद यह tthats, Im परीक्षण अभी
JK

4
हाँ, यही समस्या थी
JK

जवाबों:


264

समस्या यह थी कि मैनिफेस्ट में मेरे पास यह रेखा थी:

android:authorities="com.example.asd.fileprovider"

और जब getUriForFile पर कॉल कर रहा था, मैं गुजर रहा था:

Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile); 

इसलिए इससे बदला "com.example.asd"गया "com.example.asd.fileprovider"और इसने काम किया


1
धन्यवाद मेरे लिए काम किया। पहले मैं ऐसे ही कर रहा था। Android: प्राधिकारियों = "$ {applicationId} .fileprovider अब मैंने इसे com.memecreator में बदल दिया। Fileprovider मेरा वास्तविक पैकेज नाम
Rayyan

2
@ रयान से सहमत, android:authorities="${applicationId}"हमेशा उपयोग करने के लिए सर्वश्रेष्ठ ; कोड गलती पर कभी नहीं होगा।
सूद 28००

मेरे लिए काम किया। धन्यवाद
Landrykapela

2
यह समाधान मेरे लिए कारगर नहीं था ... मुझे यह सुनिश्चित करने के लिए जाँच करने के बाद भी अशक्त सूचक अपवाद मिल रहा है कि यह सही है।
वेस्ले फ्रेंक

44

आप एक ही डिवाइस (लगता है पर एक से अधिक वेरिएंट को चलाने के लिए सक्षम होने का एक अतिरिक्त लाभ के साथ पैकेज का नाम हार्डकोड बिना ऐसा कर सकते हैं releaseऔर debugसाथ applicationIdSuffix, देखने के इन मुद्दों ):

पर आधारित FileProvider.java:560

final ProviderInfo info = context.getPackageManager()
        .resolveContentProvider(authority, PackageManager.GET_META_DATA);
final XmlResourceParser in = info.loadXmlMetaData( //560
        context.getPackageManager(), META_DATA_FILE_PROVIDER_PATHS);

आप गलत का उपयोग कर रहे थे authorityऔर यह ContentProvider( info == null) नहीं मिला ।

अपना मेनिफेस्ट बदलें ( ${applicationId}इसे मैनिफ़ेस्ट मर्जर द्वारा बदल दिया जाएगा)

android:authorities="${applicationId}.share"

तथा

Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".share", result);

.shareप्रत्यय वैकल्पिक है, मामले में आप एक असली है ContentProviderजो अधिकारी के रूप में पैकेज नाम करने के लिए बेहतर है।


मेरे लिए काम किया है ... मैं अंतिम दो पंक्तियों और उसके काम perfectly..Thanks का इस्तेमाल किया है
रवींद्र कुशवाहा

24

मेरे मामले में, मुझे त्रुटि मिली क्योंकि

BuildConfig.APPLICATION_ID

से आयात किया जा रहा था

import android.support.v4.BuildConfig;

इसलिए यह जो स्ट्रिंग वापस आया, वह "android.support.v4"मेरे प्रोजेक्ट पैकेज नाम के बजाय था । आयात फ़ाइल की जाँच करें कि आपका import project.Buildconfigनहीं है। उदाहरण:

import com.example.yourProjectName.BuildConfig;

अंत में, <provider>मैनिफेस्ट में टैग में मुझे android:authorities="${applicationId}"हमेशा प्राधिकरण के रूप में अपने प्रोजेक्ट पैकेज का नाम प्राप्त करना होगा

<manifest>
   ..
   ..
   <application>
    ..
    ..
       <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/ruta_fileprovider" />
        </provider>

    </application>

</manifest>

1
android क्या है: संसाधन = "@ xml / ruta_fileprovider"
अनंत प्रसाद

1
@AnantaPrasad <? Xml संस्करण = "1.0" एन्कोडिंग = "utf-8"?> <पथ> <बाहरी-पथ का नाम = "external_files" path = "।" /> <फ़ाइलें-पथ नाम = "फाइलें" पथ = "।" /> <कैश-पथ का नाम = "कैश" पथ = "।" /> </ रास्तों>
राजकुमार

5

सबसे पहले, सुनिश्चित करें कि आप प्रदाता android:authoritiesअपने अन्य प्रदाताओं के साथ संघर्ष नहीं करते हैं। इसके अलावा आप इसके नाम के अंतिम भाग के लिए कोई भी नाम चुन सकते हैं: "प्रदाता", "फाइलप्रोवाइडर" आदि, लेकिन ऐप एक से अधिक android:authoritiesसूचीबद्ध होने पर दुर्घटनाग्रस्त हो जाता है , जबकि प्रलेखन में कहा गया है कि यह सूचीबद्ध कई मूल्यों की अनुमति देता है।

file://इस योजना को अब टारगेट के साथ संलग्न करने की अनुमति नहीं दी गई है targetSdkVersion> = 24 (Android N 7.0), केवल content://हमेशा सभी डिवाइसों के लिए पारित किया जाता है (Android 5, 6 और 7)। लेकिन हमने पाया कि Xiaomi इस Google सम्मेलन को तोड़ता है और भेजता है file://, इसलिए data.getData().getAuthority()खाली स्ट्रिंग देता है।

final String uriScheme = currentUri.getScheme();
if ("content".equals(uriScheme)) {
    // getting full file path (works with some providers, i.e. Gallery)
    path = FileUtils.getPath(getContext(), currentUri);
    if (path != null) {
         currentFile = new File(path);
    }
} else if ("file".equals(uriScheme)) {
    // in a rare case we received file:// in currentUri, we need to:
    // 1. create new File variable from currentUri that looks like "file:///storage/emulated/0/download/50044382b.jpg"
    // 2. generate a proper content:// Uri for it
    currentFile = new File(currentUri.getPath());
    String authority = data.getData().getAuthority();
    if (authority != null && !authority.isEmpty()) {
        currentUri = FileProvider.getUriForFile(getActivity(), authority, currentFile);
    }
} else {
    // throw exception
}

इसके अलावा, बग FileProvider.getUriForFile()जिसके परिणामस्वरूप दुर्घटना हुई java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example/files/attachments/image.jpgथी, Android समर्थन लाइब्रेरी v24.2.0 में तय किया गया था। समस्या यह थी कि FileProvider.java ने बाहरी-पथ फ़ोल्डर नहीं देखे थे।


1

यदि आप रनटाइम पर अपनी AUTHORITY का निर्माण कर रहे हैं, BuildConfigतो सुनिश्चित करें कि आप अपने पैकेज के नाम सहित पूरी कक्षा के नाम का उपयोग करते हैं।

खराब:

final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider";

अच्छा:

final String AUTHORITY = com.mycompany.myapp.BuildConfig.APPLICATION_ID + ".provider";


0

निम्नलिखित मेरे लिए काम किया।

mUri = FileProvider.getUriForFile(this,
                    BuildConfig.APPLICATION_ID + ".provider",
                    fileObject);

0

यहाँ मैं इस मुद्दे को ठीक करने के लिए क्या किया है। मैंने Android में पूरी तरह से योग्य नाम दिया: नाम। यह एंड्रॉइड 6,7,8 में काम करता है

    <provider android:authorities="${applicationId}.opener.provider" 
        android:exported="false" android:grantUriPermissions="true" 
        android:name="io.github.pwlin.cordova.plugins.fileopener2.FileProvider">
        <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" />
    </provider>

क्या आप आंतरिक निर्देशिका से फ़ाइल प्रदाता का उपयोग करके शेयर फ़ाइल के लिए अपना कोड साझा कर सकते हैं?
विशाल पाटोलिया Pat

0

आपको इसे आजमाना चाहिए:

  Context context = PostAdapter.this.activity;
                    StringBuilder stringBuilder2 = new StringBuilder();
                    stringBuilder2.append(PostAdapter.this.activity.getPackageName());
                    stringBuilder2.append(".provider");
                    Uri uri;
                    uri = FileProvider.getUriForFile(context,stringBuilder2.toString(), newFile);

0

यह वह है जो आपको करना जरूरी है:

Uri fileURI = FileProvider.getUriForFile(getActivity(), getActivity().getPackageName() + ".fileprovider", file);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.