I am downloading image file from the server and storing it on the device. When file is stored I want to show this image in any apps which support this mimetype. I am able to store the image in the storage but unable to open the file. This is my code.
private fun savePhotoToExternalStorage(displayName: String, bmp: Bitmap, mimeType:String): Boolean {
LogUtil.d(TAG, "savePhotoToExternalStorage: ")
val imageCollection = sdk29AndUp {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} ?: MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val contentValues = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, displayName)
put(MediaStore.Images.Media.MIME_TYPE, mimeType)
put(MediaStore.Images.Media.WIDTH, bmp.width)
put(MediaStore.Images.Media.HEIGHT, bmp.height)
}
return try {
context.contentResolver.insert(imageCollection, contentValues)?.also { uri ->
context.contentResolver.openOutputStream(uri).use { outputStream ->
if(!bmp.compress(Bitmap.CompressFormat.JPEG, 95, outputStream)) {
LogUtil.e(TAG, "savePhotoToExternalStorage: Exception")
}
val file = File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), displayName)
val shareUri =if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
FileProvider.getUriForFile(
context, context.packageName + ".fileprovider", file)
else
Uri.fromFile(file)
LogUtil.d(TAG, "savePhotoToExternalStorage: shareuri: $shareUri")
Log.d(TAG, "savePhotoToExternalStorage: ${shareUri.authority}")
val intent = Intent(Intent.ACTION_VIEW)
.setDataAndType(shareUri, mimeType)
.putExtra(Intent.EXTRA_STREAM, shareUri)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
LogUtil.d(TAG, "savePhotoToExternalStorage: intent: $intent")
val resolvedInfoActivities: List<ResolveInfo> =
context.packageManager.queryIntentActivities(
intent,
PackageManager.MATCH_DEFAULT_ONLY
)
for (ri in resolvedInfoActivities) {
Log.e(TAG, "resolvedInfoActivities: $ri", )
context.grantUriPermission(
ri.activityInfo.packageName,
shareUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
}
try {
context.startActivity(Intent.createChooser(intent, "Open with").addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION))
} catch (e: ActivityNotFoundException) {
e.printStackTrace()
Log.e(TAG, "savePhotoToExternalStorage: ${e.message}")
}
}
}
true
} catch(e: IOException) {
Log.e(TAG, "savePhotoToExternalStorage: ${e.message} ")
e.printStackTrace()
false
}catch (e : Exception){
Log.e(TAG, "savePhotoToExternalStorage: ${e.message}", )
e.printStackTrace()
false
}
}
I have also created the fileprovider.
fileprovider.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="files_root"
path="Android/data/${applicationId}"/>
<external-path
name="external_storage_root"
path="."/>
<external-path name="external_files" path="."/>
<files-path
name="int_files"
path="." />
<external-files-path
name="ext_files"
path="." />
<cache-path
name="int_cache"
path="." />
<external-cache-path
name="ext_cache"
path="." />
</paths>
Add provider in AndroidManifest for this provider AndroidManifest.xml
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/fileprovider" />
</provider>
This code open the intent chooser and when I select an app it shows Media not found error.
val file = File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), displayName)
You will not use the File class here. Not needed at all.
Use the uri directly.
So change
val shareUri = .... - a lot of wrong code-
to:
val shareUri = uri.
The point is that you already have a nice uri so trying to build up another one (and a wrong one) is not needed.