ফাইলপ্রভাইডার ক্র্যাশ - একটি শূন্য স্ট্রিং-এ XMLResourceParser কে আহ্বান করার চেষ্টা করছে n


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>

এটি কাঁচা / এক্সএমএল / ফাইলপথ.এক্সএমএল ফাইলপথ ফাইল file

<?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
কাঁচা / এক্সএমএল / ফাইলপথ.এক্সএমএল
— জে কে

2
কর্তৃপক্ষগুলিতে আমার কাছে প্রোপ্রাইডার রয়েছে, অ্যাপ্লিকেশন প্যাকেজটিতে সংযুক্ত আছে, তবে getUriforFile কল করার সময় আমি অ্যাপেনড করি না pro সম্ভবত এটি এখনই চলছে, আমি এখনই পরীক্ষা করছি
— জে কে

4
হ্যাঁ সমস্যাটি ছিল
— জে কে

উত্তর:


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
ধন্যবাদ আমার জন্য কাজ। প্রথমে আমি এইভাবে করছিলাম। অ্যান্ড্রয়েড কর্তৃপক্ষ = "$ {applicationId} .fileprovider এখন আমি আমার প্রকৃত প্যাকেজের নাম com.memecreator.fileprovider তা পরিবর্তিত
— Rayyan

2
@ রায়ানের সাথে সম্মত হন, android:authorities="${applicationId}"সর্বদা ব্যবহারের জন্য সেরা ; কোড কখনই ভুল হবে না।
— Sud007

আমার জন্য কাজ করেছেন। ধন্যবাদ
— ল্যান্ড্রিকেপেলা

2
এই সমাধানটি আমার পক্ষে কার্যকর হয়নি ... আমি সঠিক কিনা তা পরীক্ষা করার পরেও নাল পয়েন্টার ব্যতিক্রম পাচ্ছি।
— ওয়েসলি

44

আপনি একই ডিভাইস (মনে একাধিক রূপগুলো চালাতে পারছে না একটি অতিরিক্ত সুবিধার সঙ্গে প্যাকেজের নাম hardcoding ছাড়া এটা করতে পারেন 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যা কর্তৃপক্ষ হিসাবে প্যাকেজের নাম আছে উত্তম।


আমার জন্য কাজ করেছেন ... আমি শেষ দুটি লাইন এবং এর কাজটি পুরোপুরি ব্যবহার
— করেছি..ধন্যবাদ

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
অ্যান্ড্রয়েড কী: সংস্থান = "@ xML / ruta_fileprovider"
— অনন্ত প্রসাদ

1
@ অ্যান্টনাপ্রসাদ <? এক্সএমএল সংস্করণ = "1.0" এনকোডিং = "ইউটিএফ -8"?> <প্যাথস> <বাহ্যিক-পথের নাম = "বহিরাগত_ফায়ালস" পথ = "" " /> <ফাইল-পথের নাম = "ফাইলগুলি" পথ = "।" /> <ক্যাশে-পথের নাম = "ক্যাশে" পথ = "।" /> </paths>
— প্রিন্স

5

প্রথমে নিশ্চিত হয়ে নিন যে আপনি সরবরাহকারী android:authoritiesআপনার অন্যান্য সরবরাহকারীদের সাথে দ্বন্দ্ব করছেন না। এছাড়াও এর নামের শেষ অংশের জন্য আপনি যে কোনও নাম চয়ন করতে পারেন: "সরবরাহকারী", "ফাইলপ্রোভাডার" ইত্যাদি but তবে একাধিক android:authoritiesতালিকাভুক্ত থাকা অবস্থায় অ্যাপ ক্র্যাশ হয় , অন্যদিকে ডকুমেন্টেশন বলে যে এটি একাধিক মান তালিকাভুক্ত করার অনুমতি দেয়।

file://টার্গেটএসডিপি ভার্সন> = 24 (অ্যান্ড্রয়েড এন 7.0) এ স্কেন্টটি এখন ইন্টেন্টের সাথে সংযুক্ত হওয়ার অনুমতি নেই, কেবল content://সর্বদা সমস্ত ডিভাইসের (অ্যান্ড্রয়েড 5, 6 এবং 7) এর জন্য পাস করা হয়। তবে আমরা মুখোমুখি হয়েছি যে শাওমি এই গুগল কনভেনশনটি ভেঙে পাঠায়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হওয়ার ফলে বাগটি অ্যান্ড্রয়েড সমর্থন লাইব্রেরি v24.2.0 এ স্থির করা হয়েছিল। সমস্যাটি ছিল ফাইলপ্রভাইডার.জাভা বাহ্যিক-পথ ফোল্ডারগুলি দেখেনি।


1

যদি আপনি রানটাইম ব্যবহার করে আপনার সত্যতা তৈরি করে থাকেন 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

সমস্যাটি সমাধান করার জন্য আমি এখানে যা করেছি। আমি অ্যান্ড্রয়েডে পুরোপুরি যোগ্য নাম দিয়েছি: নাম। এটি অ্যান্ড্রয়েড 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>

আপনি কি দয়া করে অভ্যন্তরীণ ডিরেক্টরি থেকে ফাইল সরবরাহকারীর ব্যবহার করে শেয়ার ফাইলের জন্য আপনার কোডটি ভাগ করতে পারেন?
— বিশাল পাটোলিয়া ツ

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);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.