studio link intent extra_stream and action_send android android-intent

link - Android Share Intent para un mapa de bits: ¿es posible no guardarlo antes de compartirlo?



share text android intent (5)

Intento exportar un mapa de bits desde mi aplicación utilizando la intención de compartir sin guardar un archivo para una ubicación temporal. Todos los ejemplos que encontré son de dos pasos 1) guardar en la tarjeta SD y crear Uri para ese archivo 2) iniciar la intención con este URI

¿Es posible hacerlo sin requerir el permiso WRITE_EXTERNAL_STORAGE, guardando el archivo [y quitándolo después]? ¿Cómo abordar dispositivos sin ExternalStorage?


Intento exportar un mapa de bits desde mi aplicación utilizando la intención de compartir sin guardar un archivo para una ubicación temporal.

En teoría, esto es posible. En la práctica, probablemente no sea posible.

En teoría, todo lo que necesita compartir es un Uri que se resolverá en el mapa de bits. El enfoque más simple es si ese es un archivo al que la otra aplicación puede acceder directamente, como en el almacenamiento externo.

Para no escribirlo en absoluto, necesitaría implementar su propio ContentProvider , descubrir cómo implementar openFile() para devolver su mapa de bits en memoria, y luego pasar un Uri que represente ese mapa de bits en la Intent ACTION_SEND . Como openFile() necesita devolver un ParcelFileDescriptor , no sé cómo lo haría sin una representación en disco, pero no he dedicado mucho tiempo a buscar.

¿Es posible hacerlo sin requerir el permiso WRITE_EXTERNAL_STORAGE, guardando el archivo [y quitándolo después]?

Si simplemente no lo quiere en el almacenamiento externo, puede ir a la ruta ContentProvider , usando un archivo en el almacenamiento interno. Este proyecto de ejemplo muestra un ContentProvider que sirve un archivo PDF a través de ACTION_VIEW a un visor de PDF en un dispositivo; el mismo enfoque podría usarse para ACTION_SEND .


Aquí está el método de trabajo para hacer una captura de pantalla de la propia aplicación y compartirla como imagen a través de cualquier messanger o cliente de correo electrónico.

Para arreglar el mapa de bits que no actualizaba el problema, mejoré la respuesta de Suragch , usando el comentario de Gurupad Mamadapur y añadí modificaciones propias.

Aquí hay un código en lenguaje Kotlin :

private lateinit var myRootView:View // root view of activity @SuppressLint("SimpleDateFormat") private fun shareScreenshot() { // We need date and time to be added to image name to make it unique every time, otherwise bitmap will not update val sdf = SimpleDateFormat("yyyyMMdd_HHmmss") val currentDateandTime = sdf.format(Date()) val imageName = "/image_$currentDateandTime.jpg" // CREATE myRootView = window.decorView.rootView myRootView.isDrawingCacheEnabled = true myRootView.buildDrawingCache(true) // maybe You dont need this val bitmap = Bitmap.createBitmap(myRootView.drawingCache) myRootView.isDrawingCacheEnabled = false // SAVE try { File(this.cacheDir, "images").deleteRecursively() // delete old images val cachePath = File(this.cacheDir, "images") cachePath.mkdirs() // don''t forget to make the directory val stream = FileOutputStream("$cachePath$imageName") bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream) // can be png and any quality level stream.close() } catch (ex: Exception) { Toast.makeText(this, ex.javaClass.canonicalName, Toast.LENGTH_LONG).show() // You can replace this with Log.e(...) } // SHARE val imagePath = File(this.cacheDir, "images") val newFile = File(imagePath, imageName) val contentUri = FileProvider.getUriForFile(this, "com.example.myapp.fileprovider", newFile) if (contentUri != null) { val shareIntent = Intent() shareIntent.action = Intent.ACTION_SEND shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) // temp permission for receiving app to read this file shareIntent.type = "image/jpeg" // just assign type. we don''t need to set data, otherwise intent will not work properly shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri) startActivity(Intent.createChooser(shareIntent, "Choose app")) } }


Esto para compartir CardView como una Imagen y luego guardarlo en el subdirectorio de caché del área de almacenamiento interno de la aplicación. Espero que sea de ayuda.

@Override public void onClick(View view) { CardView.setDrawingCacheEnabled(true); CardView.buildDrawingCache(); Bitmap bitmap = CardView.getDrawingCache(); try{ File file = new File(getContext().getCacheDir()+"/Image.png"); bitmap.compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(file)); Uri uri = FileProvider.getUriForFile(getContext(),"com.mydomain.app", file); Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); shareIntent.putExtra(Intent.EXTRA_STREAM, uri); shareIntent.setType("image/jpeg"); getContext().startActivity(Intent.createChooser(shareIntent, "Share")); }catch (FileNotFoundException e) {e.printStackTrace();} } });


Si alguien todavía está buscando una solución fácil y corta sin ningún permiso de almacenamiento (admite también el turrón 7.0). Aquí está.

Añadir esto en Manifiesto

<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> </provider>

Ahora crea provider_paths.xml

<paths> <external-path name="external_files" path="."/> </paths>

Finalmente, agregue este método a su actividad / fragmento (rootView es la vista que desea compartir)

private void ShareIt(View rootView){ if (rootView != null && context != null && !context.isFinishing()) { rootView.setDrawingCacheEnabled(true); Bitmap bitmap = Bitmap.createBitmap(rootView.getDrawingCache()); if (bitmap != null ) { //Save the image inside the APPLICTION folder File mediaStorageDir = new File(AppContext.getInstance().getExternalCacheDir() + "Image.png"); try { FileOutputStream outputStream = new FileOutputStream(String.valueOf(mediaStorageDir)); bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); outputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } if (ObjectUtils.isNotNull(mediaStorageDir)) { Uri imageUri = FileProvider.getUriForFile(getActivity(), getActivity().getApplicationContext().getPackageName() + ".provider", mediaStorageDir); if (ObjectUtils.isNotNull(imageUri)) { Intent waIntent = new Intent(Intent.ACTION_SEND); waIntent.setType("image/*"); waIntent.putExtra(Intent.EXTRA_STREAM, imageUri); startActivity(Intent.createChooser(waIntent, "Share with")); } } } } }


Yo tuve el mísmo problema. No quería tener que pedir permiso de lectura y escritura de almacenamiento externo. Además, a veces hay problemas cuando los teléfonos no tienen tarjetas SD o las tarjetas se desmontan.

El siguiente método usa un ContentProvider llamado FileProvider . Técnicamente, aún está guardando el mapa de bits (en el almacenamiento interno) antes de compartirlo, pero no necesita solicitar ningún permiso. Además, cada vez que comparte el mapa de bits, el archivo de imagen se sobrescribe. Y dado que está en la memoria caché interna, se eliminará cuando el usuario desinstale la aplicación. Entonces, en mi opinión, es tan bueno como no guardar la imagen. Este método también es más seguro que guardarlo en un almacenamiento externo.

La documentación es bastante buena (ver la Lectura Adicional a continuación), pero algunas partes son un poco complicadas. Aquí hay un resumen que funcionó para mí.

Configurar el FileProvider en el Manifiesto

<manifest> ... <application> ... <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.example.myapp.fileprovider" android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" /> </provider> ... </application> </manifest>

Reemplace com.example.myapp con el nombre del paquete de su aplicación.

Crea res / xml / filepaths.xml

<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <cache-path name="shared_images" path="images/"/> </paths>

Esto le dice al FileProvider dónde obtener los archivos para compartir (usando el directorio de caché en este caso).

Guarde la imagen en el almacenamiento interno

// save bitmap to cache directory try { File cachePath = new File(context.getCacheDir(), "images"); cachePath.mkdirs(); // don''t forget to make the directory FileOutputStream stream = new FileOutputStream(cachePath + "/image.png"); // overwrites this image every time bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); stream.close(); } catch (IOException e) { e.printStackTrace(); }

Comparte la imagen

File imagePath = new File(context.getCacheDir(), "images"); File newFile = new File(imagePath, "image.png"); Uri contentUri = FileProvider.getUriForFile(context, "com.example.myapp.fileprovider", newFile); if (contentUri != null) { Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // temp permission for receiving app to read this file shareIntent.setDataAndType(contentUri, getContentResolver().getType(contentUri)); shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri); startActivity(Intent.createChooser(shareIntent, "Choose an app")); }

Otras lecturas