2015-06-17 1 views
51

Это часть моего манифеста:FileProvider аварии - NPE попытке вызвать XmlResourceParser на нулевую строку

<?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) 
+0

«Это файл Пути к файлам» - где именно в вашем проекте этот файл? – CommonsWare

+0

raw/xml/filepaths.xml –

+1

у меня есть .provider, добавленный в пакет приложения, но при вызове getUriForFile я не добавляю .provider. может быть, это так, Im тестирование прямо сейчас –

ответ

115

Проблема заключалась в том, что в манифесте я имел следующую строку:

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

и при вызове getUriForFile я проходил мимо:

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

Так изменился с "com.example.asd" до "com.example.asd.fileprovider" и работал

+0

cool It's working –

+0

Спасибо, работал для меня. Сначала я так делал. android: authority = "$ {applicationId} .fileprovider Теперь я изменил его на com.memecreator.fileprovider мое фактическое имя пакета – Rayyan

+0

Согласен с @Rayyan, Лучше всего использовать' android: authority = "$ {applicationId}" 'всегда, код будет никогда не виноват. – sud007

25

Вы можете сделать это без жесткого кодирования имя пакета с дополнительным преимуществом является возможность запускать несколько вариантов на одном устройстве (думаю release и debug с applicationIdSuffix см these issues):

на основе 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} будет заменен Manifest Присоединения)

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

и

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

Суффикс .share является обязательным, в случае, если у вас есть реальный ContentProvider, который лучше иметь имя пакета как полномочия.

2

Во-первых, убедитесь, что поставщик android:authorities не конфликтует с вашими другими провайдерами. Кроме того, вы можете выбрать любое имя для последней части своего имени: «поставщик», «файлпровайдер» и т. Д., Но приложение выйдет из строя, если перечислено более одного android:authorities, тогда как документация заявляет, что она позволяет перечислять несколько значений.

file:// схеме в настоящее время не разрешено прикреплять с помощью Intent на 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 не видел папки внешнего пути.

0

Если вы строите свой АВТОРИТЕТ во время выполнения, используя BuildConfig, убедитесь, что вы используете полное имя класса, включая имя вашего пакета.

Bad:

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

Хорошо:

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

-1

Вслед работал для меня.

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

В моем случае, я получил ошибку, потому что

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> 
Смежные вопросы