paths geturiforfile generic fileprovider android

geturiforfile - import file provider android



Accidente de FileProvider: npe que intenta invocar XmlResourceParser en una cadena nula (8)

Esta es una parte de mi manifiesto:

<?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>

Este es el archivo filepaths en 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>

Descargo un video de Internet y lo guardo en el almacenamiento interno de esta manera:

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; } }

Intento usarlo así:

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(); } }

En esta línea:

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

Obtuve el siguiente error:

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)


Deberías probarlo:

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);


El problema era que en Manifiesto tenía esta línea:

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

y al llamar a getUriForFile estaba pasando:

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

Así que cambió de "com.example.asd" a "com.example.asd.fileprovider" y funcionó


En mi caso, recibí el error porque el

BuildConfig.APPLICATION_ID

estaba siendo importado de

import android.support.v4.BuildConfig;

Entonces, la cadena que devolvió fue "android.support.v4" lugar del nombre del paquete de mi proyecto. Echa un vistazo a que el archivo de importación es de tu import project.Buildconfig . Ejemplo:

import com.example.yourProjectName.BuildConfig;

Finalmente, en la etiqueta <provider> en Manifest tengo android:authorities="${applicationId}" para obtener siempre el nombre del paquete de mi proyecto como autoridad

<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>


Esto es lo que hice para solucionar el problema. Di nombre completo en Android: nombre. Funciona en 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>


Lo siguiente funcionó para mí.

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


Primero, asegúrese de que su proveedor de android:authorities no entren en conflicto con sus otros proveedores. Además de eso, puede elegir cualquier nombre para la última parte de su nombre: "proveedor", "proveedor de archivos", etc., pero la aplicación se bloquea cuando hay más de un android:authorities enumeradas, mientras que la documentación indica que permite que se enumeren varios valores.

file:// esquema file:// ahora no se puede adjuntar con Intent en targetSdkVersion> = 24 (Android N 7.0), solo el content:// siempre se pasa para todos los dispositivos (Android 5, 6 y 7). Pero descubrimos que Xiaomi rompe esta convención de Google y envía el file:// , de ahí data.getData().getAuthority() da una cadena vacía.

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 }

Además, el error cuando FileProvider.getUriForFile() resultó en un bloqueo java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example/files/attachments/image.jpg se corrigió en la Biblioteca de soporte de Android v24.2.0. El problema era que FileProvider.java no veía carpetas de ruta externa.


Puede hacerlo sin codificar el nombre del paquete con un beneficio adicional de poder ejecutar múltiples variantes en el mismo dispositivo (piense en release y debug con applicationIdSuffix , vea estos problemas ):

Basado en 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);

estaba utilizando la authority incorrecta y no encontró ContentProvider ( info == null ).

Cambie su manifiesto a ( ${applicationId} será reemplazado por Manifest Merger)

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

y

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

El sufijo .share es opcional, en caso de que tenga un ContentProvider real que es mejor tener el nombre del paquete como autoridad.


Si está creando su AUTORIDAD en tiempo de ejecución con BuildConfig asegúrese de usar el nombre completo de la clase, incluido el nombre del paquete.

Malo:

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

Bueno:

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