To jest część mojego manifestu:
<?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>
To jest plik filepaths w raw / 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>
Pobieram film z internetu i zapisuję go w pamięci wewnętrznej w ten sposób:
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;
}
}
Staram się go używać tak:
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();
}
}
W tej linii:
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile);
Otrzymuję następujący błąd:
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)
Odpowiedzi:
Problem polegał na tym, że w Manifest miałem taką linijkę:
a dzwoniąc getUriForFile mijałem:
Tak się zmieniło z
"com.example.asd"
na"com.example.asd.fileprovider"
i zadziałałoźródło
android:authorities="${applicationId}"
zawsze; kod nigdy nie będzie winny.Można to zrobić bez hardcoding nazwę pakietu z dodatkową korzyścią jest w stanie uruchomić wiele wariantów na tym samym urządzeniu (myślę
release
idebug
zapplicationIdSuffix
, zobacz te problemy ):Oparte na
FileProvider.java:560
użyłeś niewłaściwego
authority
i nie znalazłeśContentProvider
(info == null
).Zmień swój manifest na (
${applicationId}
zostanie zastąpiony przez Manifest Merger)i
.share
Przyrostek jest opcjonalny, w przypadku, gdy mają realnąContentProvider
, która jest lepiej mieć nazwę pakietu jako instytucję.źródło
W moim przypadku wystąpił błąd, ponieważ plik
był importowany z
Więc ciąg, który zwrócił, był
"android.support.v4"
zamiast nazwy mojego pakietu projektu. Sprawdź, czy plik importu pochodzi z Twojego,import project.Buildconfig
a nie innego. Przykład:Wreszcie, w
<provider>
tagu w Manifest, muszęandroid:authorities="${applicationId}"
zawsze mieć nazwę mojego pakietu projektu jako organźródło
Po pierwsze, upewnij się, że
android:authorities
Twój dostawca nie koliduje z innymi dostawcami. Poza tym możesz wybrać dowolną nazwę dla ostatniej części nazwy: „dostawca”, „dostawca plików” itp., Ale aplikacja ulega awarii, gdy jest więcej niż jedenandroid:authorities
, podczas gdy dokumentacja stwierdza, że zezwala na wyświetlanie wielu wartości.file://
Schemat nie może być teraz dołączany z Intent do targetSdkVersion> = 24 (Android N 7.0), tylkocontent://
jest zawsze przekazywany dla wszystkich urządzeń (Android 5, 6 i 7). Ale napotkaliśmy, że Xiaomi łamie tę konwencję Google i wysyłafile://
, stąddata.getData().getAuthority()
podaje pusty ciąg.Ponadto błąd
FileProvider.getUriForFile()
powodujący awarięjava.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example/files/attachments/image.jpg
został naprawiony w bibliotece obsługi Androida w wersji 24.2.0. Problem polegał na tym, że FileProvider.java nie widział folderów ze ścieżkami zewnętrznymi.źródło
Jeśli budujesz AUTORYTET w czasie wykonywania przy użyciu,
BuildConfig
upewnij się, że używasz pełnej nazwy klasy, w tym nazwy pakietu.Zły:
final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider";
Dobry:
final String AUTHORITY = com.mycompany.myapp.BuildConfig.APPLICATION_ID + ".provider";
źródło
Następujące pracowały dla mnie.
źródło
Oto, co zrobiłem, aby rozwiązać problem. Podałem w pełni kwalifikowaną nazwę w android: name. Działa na Androidzie 6,7,8
źródło
Powinieneś spróbować:
źródło
Oto, co musisz zrobić:
źródło