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

 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.

¿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ó.

  • Selector de Android Drawable con VectorDrawables srcCompat
  • Cambiar color de sugerencia de EditText cuando se utiliza TextInputLayout
  • CollapsingToolbarLayout ImageView no se puede desplazar
  • CardView va encima de FrameLayout, pero declaró primero
  • Android studio 1.5.1: No se pudo encontrar la propiedad 'vectorDrawables'
  • Instale el paquete: 'Android Support Library'
  • Cómo deshabilitar "expandir" de AppBarLayout en el fragmento que tiene un NestedScrollView?
  • AppCompatSpinner vs android.widget.Spinner para la aplicación con min SDK versión 14
  • Android BottomSheetDialogFragment no se expande por completo
  • Cómo implementar correctamente NestedScrollingChild en un WebView
  • Diferentes resultados de CardView de la Biblioteca de soporte de Android en diferentes dispositivos
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.