Обновление: Эта проблема была исправлена в версии Instagram, выпущенной ранее на этой неделе. Временные решения больше не нужны.
Ни одно из упомянутых выше решений не сработало для меня, так как кажется, что прямое распространение через ContentProvider
или его производную FileProvider
было нарушено из-за изменений, внесенных в приложение Instagram.
Я заметил, что обмен Uri MediaStore
контентом по-прежнему работает, поскольку другие приложения, такие как Google Photos, которые пишут в MediaStore до публикации, все еще могут обмениваться изображениями для подачи.
Вы можете вставить изображение File
в MediaStore
следующим образом:
@SuppressLint("InlinedApi")
fun insertImageToMediaStore(file: File, relativePath: String): Uri? {
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, file.name)
val mimeType = when (file.extension) {
"jpg", "jpeg" -> "jpeg"
"png" -> "png"
else -> return null
}
put(MediaStore.Images.Media.MIME_TYPE, "image/$mimeType")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
put(MediaStore.MediaColumns.RELATIVE_PATH, relativePath)
put(MediaStore.MediaColumns.IS_PENDING, 1)
}
}
val collection = when (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
true -> MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
false -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
val uri = contentResolver.insert(collection, values)
uri?.let {
contentResolver.openOutputStream(uri)?.use { outputStream ->
try {
outputStream.write(file.readBytes())
outputStream.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
values.clear()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
values.put(MediaStore.Images.Media.IS_PENDING, 0)
contentResolver.update(uri, values, null, null)
}
} ?: throw RuntimeException("MediaStore failed for some reason")
return uri
}
Затем, вернув Uri
, отправьте его через Intent следующим образом:
val filePath = "/data/data/io.jammy.withintent/files/IMG-20200321_093350_2020-122758.jpg" // this is an example path from an app-internal image file
val context: Context? = this
val intent = Intent(Intent.ACTION_SEND)
intent.type = "image/*"
insertImageToMediaStore(File(filePath), "Pictures/Your Subdirectory")?.let { uri ->
val clipData = ClipData.newRawUri("Image", uri)
intent.clipData = clipData
intent.putExtra(Intent.EXTRA_STREAM, uri)
val target = Intent.createChooser(intent, "Share Image")
target?.let { context?.startActivity(it) }
} ?: run {
Log.e(TAG, "Unsupported image file")
return
}
Хотя это и не идеально, поскольку изображение затем записывается в MediaStore
, что может быть нежелательным поведением во многих случаях, оно снова дает возможность делиться в среднесрочной перспективе, в то время как Instagram исправляет их возгласы ie.