Proporcionar icono a selector de sistema a través de ChooserTargetService, FileProvider y grantUriPermission
Tengo algunas imágenes almacenadas en la aplicación local conectada con ciertos contextos (como contactos). Estoy usando el recurso compartido directo (API 23+) a través de ChooserTargetService
para mostrar estos para elegir y quiero que ChooserTarget
instancias de ChooserTarget
tengan Icon
lleno de estas imágenes.
Así que pensé que podía usar android.support.v4.content.FileProvider
para esto (dentro de ChooserTargetService::onGetChooserTargets
):
- Cómo eliminar el relleno superior y inferior de android.support.v7.widget.Toolbar?
- Appcompat v21 lanza java.lang.UnsupportedOperationException
- AppCompat 23.2 utiliza VectorDrawableCompat con RemoteViews (AppWidget) en la API <21
- Cómo agregar Android Support v7 bibliotecas en eclipse?
- Implementación del menú de acción flotante mediante el botón de acción Float de Android Design Support library
val file = File(File(filesDir, "images"), imageFileName) val contentUri = FileProvider.getUriForFile(this, "com.company.fileprovider", file) val icon = Icon.createWithContentUri(contentUri)
Y en Manifiesto:
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.mycompany.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_provider_paths"/> </provider>
Pero el problema es que recibo una excepción
05-10 16:06:09.100 32444-32444/android:ui W/Icon: Unable to load image from URI: content://com.mycompany.fileprovider/images/icon_dice.png java.lang.SecurityException: Permission Denial: reading android.support.v4.content.FileProvider uri content://com.mycompany.fileprovider/images/icon_dice.png from pid=32444, uid=1000 requires the provider be exported, or grantUriPermission() at android.os.Parcel.readException(Parcel.java:1684) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183) at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:146) at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:692) at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1147) at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:984) at android.content.ContentResolver.openInputStream(ContentResolver.java:704) at android.graphics.drawable.Icon.loadDrawableInner(Icon.java:335) at android.graphics.drawable.Icon.loadDrawable(Icon.java:272) at com.android.internal.app.ChooserActivity$ChooserTargetInfo.<init>(ChooserActivity.java:645) at com.android.internal.app.ChooserActivity$ChooserListAdapter.addServiceResults(ChooserActivity.java:1003) at com.android.internal.app.ChooserActivity$1.handleMessage(ChooserActivity.java:126) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
No es posible seguir la sugerencia "exportada", porque FileProvider
desafortunadamente la tiene codificada para no permitirla (del código fuente de la biblioteca de soporte de FileProvider.java
android):
// Sanity check our security if (info.exported) { throw new SecurityException("Provider must not be exported"); } if (!info.grantUriPermissions) { throw new SecurityException("Provider must grant uri permissions"); }
Así que traté de llamar
grantUriPermission("<something goes here>", contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
Pero no es obvio lo que se debe poner como nombre del paquete primer parámetro. De los detalles de excepción se puede deducir que el código está en com.android.internal.app.ChooserActivity
y es llamado por el sistema.
Editar:
Usar Icon.createWithFilePath
no es posible, porque no puede tener acceso al archivo de proceso diferente:
W/Icon: Unable to load image from path: /data/user/0/com.mycompany.app/files/images/image.png java.io.FileNotFoundException: /data/user/0/com.mycompany.app/files/images/image.png (Permission denied)
Y si intenta establecer el archivo en Context.MODE_WORLD_READABLE
obsoleto, obtiene:
java.lang.SecurityException: MODE_WORLD_READABLE no longer supported
En Andorid 7.
- Guardar BottomNavigationVer el elemento seleccionado durante la rotación de la pantalla
- Librería de soporte de Android 23.2 vector drawables are blurry
- Impedir que RecyclerView se desplace en AppBarLayout antes de que AppBarLayout se colapse.
- Android AppCompat 23.1.0 Tinte Compuesto Dibujable
- Cómo solucionar "Support-v13: 19.1.0 depende de las bibliotecas, pero no es una biblioteca en sí"?
- Color del texto del botón AlertDialog con la biblioteca de soporte v24.2.1
- Extraer los atributos de diseño de la biblioteca de soporte en estilos
- Cómo establecer el comportamiento de comprobación compartida en todos los grupos en NavigationView?
¿Por qué no crear la imagen del icono con los datos del archivo antes de crear el ChooserTarget
. Esto es lo que hace la aplicación Messenger de Google.
File file = new File(new File(filesDir, "images"), imageFileName); Bitmap b = BitmapFactory.decodeStream(new FileInputStream(file)); Icon icon = Icon.createWithBitmap(b); return new ChooserTarget(title, icon, score, cn, extras);
Incluso podría agregar algo de compresión al mapa de bits si está tan inclinado.
Sin embargo, tengo que advertir que usted necesita ser cuidadoso de la cantidad y el tamaño de éstos que usted está poniendo a través del cuaderno … éstos son objetos parcelables y, a partir de 7.0, el carpeta puede lanzar TransacationTooLargeException
si usted pone también Muchos o demasiado grandes de Bitmaps en estos ChooserTarget
s o cualquier Parcelable enviado a través de él.
MODE_WORLD_READABLE es una falla de seguridad.
Por lo tanto, google primero desaprobado y luego completamente eliminado.
MODE_WORLD_READABLE fue obsoleto en versiones hasta Android M. Y en Android N ya no es compatible y lanza SecurityException.
Solución: pruebe por favor un diverso modo. Utilicé Context.MODE_PRIVATE y funcionó.
- ¿Cómo pasar el texto a Google Voice SMS mediante programación?
- Sombras de OpenGL ES para los sprites 2D