Ich hatte das gleiche Problem. Ich wollte nicht nach den Lese- und Schreibberechtigungen für externen Speicher fragen müssen. Manchmal gibt es auch Probleme, wenn Telefone keine SD-Karten haben oder die Karten nicht mehr montiert werden.
Die folgende Methode verwendet einen ContentProvider namens FileProvider . Technisch gesehen speichern Sie die Bitmap (im internen Speicher) noch vor der Freigabe, müssen jedoch keine Berechtigungen anfordern. Außerdem wird die Bilddatei jedes Mal, wenn Sie die Bitmap freigeben, überschrieben. Und da es sich im internen Cache befindet, wird es gelöscht, wenn der Benutzer die App deinstalliert. Meiner Meinung nach ist es genauso gut, das Bild nicht zu speichern. Diese Methode ist auch sicherer als das Speichern im externen Speicher.
Die Dokumentation ist ziemlich gut (siehe weiterführende Literatur unten), aber einige Teile sind etwas knifflig. Hier ist eine Zusammenfassung, die für mich funktioniert hat.
Richten Sie den FileProvider im Manifest ein
<manifest>
...
<application>
...
<provider
android:name="androidx.core.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>
Ersetzen Sie com.example.myapp
durch Ihren App-Paketnamen.
Erstellen Sie 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>
Dies teilt dem FileProvider mit, wo die Dateien freigegeben werden sollen (in diesem Fall über das Cache-Verzeichnis).
Speichern Sie das Bild im internen Speicher
try {
File cachePath = new File(context.getCacheDir(), "images");
cachePath.mkdirs();
FileOutputStream stream = new FileOutputStream(cachePath + "/image.png");
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
Teile das Bild
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);
shareIntent.setDataAndType(contentUri, getContentResolver().getType(contentUri));
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
startActivity(Intent.createChooser(shareIntent, "Choose an app"));
}
Weiterführende Literatur