J’essaie d’exporter un bitmap de mon application en utilisant l’intention de partager sans enregistrer un fichier pour un emplacement temporel. Tous les exemples que j’ai trouvés sont en deux étapes 1) enregistrer sur la carte SD et créer Uri pour ce fichier 2) lancer l’intention avec cet Uri
Est-il possible de le faire sans autorisation WRITE_EXTERNAL_STORAGE, en enregistrant le fichier [et en le supprimant ensuite]? Comment adresser des périphériques sans ExternalStorage?
J’ai eu le même problème. Je ne voulais pas avoir à demander les permissions de stockage externe en lecture et en écriture. De plus, il arrive parfois que les téléphones ne disposent pas de cartes SD ou que les cartes ne soient pas démontées.
La méthode suivante utilise un ContentProvider appelé FileProvider . Techniquement, vous enregistrez toujours le bitmap (dans le stockage interne) avant de le partager, mais vous n’avez pas besoin de demander d’autorisation. De plus, chaque fois que vous partagez le bitmap, le fichier image est écrasé. Et comme il se trouve dans le cache interne, il sera supprimé lorsque l’utilisateur désinstalle l’application. Donc, à mon avis, c’est aussi bon que de ne pas enregistrer l’image. Cette méthode est également plus sécurisée que son enregistrement sur un stockage externe.
La documentation est plutôt bonne (voir la section suivante), mais certaines parties sont un peu délicates. Voici un résumé qui a fonctionné pour moi.
... ... ...
Remplacez com.example.myapp
par le nom de votre package d’application.
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")); }
J’essaie d’exporter un bitmap de mon application en utilisant l’intention de partager sans enregistrer un fichier pour un emplacement temporel.
En théorie, c’est possible. En pratique, ce n’est probablement pas possible.
En théorie, tout ce que vous devez partager est un Uri
qui se résoudra au bitmap. L’approche la plus simple consiste à savoir s’il s’agit d’un fichier directement accessible par l’autre application, par exemple sur un stockage externe.
Pour ne pas l’écrire du tout, vous devez implémenter votre propre ContentProvider
, déterminer comment implémenter openFile()
pour renvoyer votre bitmap en mémoire, puis transmettre un Uri
représentant ce bitmap dans l’ Intent
ACTION_SEND
. Comme openFile()
doit retourner un ParcelFileDescriptor
, je ne sais pas comment vous le feriez sans une représentation sur disque, mais je n’ai pas passé beaucoup de temps à chercher.
Est-il possible de le faire sans autorisation WRITE_EXTERNAL_STORAGE, en enregistrant le fichier [et en le supprimant ensuite]?
Si vous ne le souhaitez tout simplement pas sur un stockage externe, vous pouvez accéder à l’itinéraire ContentProvider
utilisant un fichier de stockage interne. Cet exemple de projet illustre un ContentProvider
qui ContentProvider
un fichier PDF via ACTION_VIEW
à un ACTION_VIEW
de PDF sur un périphérique; la même approche pourrait être utilisée pour ACTION_SEND
.
Ceci pour partager CardView en tant qu’image, puis l’enregistrer dans le sous-répertoire cache de la zone de stockage interne de l’application. J’espère que ce sera utile.
@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();} } });
Pour corriger le problème de la mise à jour de l’ image bitmap , j’ai amélioré la réponse de Suragch , en utilisant le commentaire de Gurupad Mamadapur et en y ajoutant ses propres modifications.
Voici le code en langue 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")) } }
Si quelqu’un est toujours à la recherche d’une solution simple et rapide sans autorisation de stockage (prend également en charge nougat 7.0). C’est ici.
Ajouter ceci dans Manifest
Maintenant, créez provider_paths.xml
Enfin, ajoutez cette méthode à votre activité / fragment (rootView est la vue que vous souhaitez partager)
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(Ssortingng.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")); } } } } }