Это часть моего манифеста:
<?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>
Это файл путей к файлам в 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>
Я скачиваю видео из интернета и сохраняю его во внутреннем хранилище следующим образом:
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)
Ответы:
Проблема заключалась в том, что в Manifest у меня была такая строка:
android:authorities="com.example.asd.fileprovider"
и при вызове getUriForFile я передавал:
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.example.asd", newFile);
Так изменилось с
"com.example.asd"
на,"com.example.asd.fileprovider"
и это сработалоисточник
android:authorities="${applicationId}"
всегда; код никогда не будет виноват.Вы можете сделать это без жесткого кодирования имени пакета с дополнительным преимуществом возможности запускать несколько вариантов на одном устройстве (подумайте
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}
будет заменен Manifest Merger)android:authorities="${applicationId}.share"
а также
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".share", result);
.share
Суффикс не является обязательным, в случае , если у вас есть реальный ,ContentProvider
который лучше иметь имя пакета в качестве органа.источник
В моем случае я получил ошибку, потому что
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>
источник
Во-первых, убедитесь, что ваш провайдер
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 }
Также в библиотеке поддержки Android v24.2.0 исправлена ошибка,
FileProvider.getUriForFile()
приводившая к сбоюjava.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example/files/attachments/image.jpg
. Проблема заключалась в том, что FileProvider.java не видел папки внешнего пути.источник
Если вы создаете свой АВТОРИТЕТ во время выполнения, используя
BuildConfig
убедитесь, что вы используете полное имя класса, включая имя вашего пакета.Плохой:
final String AUTHORITY = BuildConfig.APPLICATION_ID + ".provider";
Хороший:
final String AUTHORITY = com.mycompany.myapp.BuildConfig.APPLICATION_ID + ".provider";
источник
Следующее сработало для меня.
mUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", fileObject);
источник
Вот что я сделал, чтобы исправить проблему. Я дал полное имя в android: name. Работает в 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>
источник
Тебе стоит попробовать это:
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);
источник
Вот что вам нужно сделать:
Uri fileURI = FileProvider.getUriForFile(getActivity(), getActivity().getPackageName() + ".fileprovider", file);
источник