使用 Uri -> 从图像选择器显示图像有效,但从 db room 不显示图像...(Jetpack Compose)

Sah*_*ous 7 android uri android-jetpack-compose

我有一个来电应用程序,允许用户从手机中选取联系人照片和铃声音频文件。\n当我选取照片时,可以使用界面上的 URI 正确显示它。在主页和联系页面上。\n我将其保存在房间数据库中...

\n

如果我关闭应用程序并重新打开它,它会从数据库获取相同的 URI。但没有显示图像。无论是在主页还是联系页面上。 \ni 尝试手动插入 URI 代码,它也没有显示任何内容...还将图像加载器更改为GlideImagefrom rememberImagePainter(另一个实现),但同样的问题...\n我的 URI来自数据库和图像选择器看起来像这样\nval uri2:Uri = "content://com.android.providers.media.documents/document/image%3A34".toUri()

\n

拾取图像Uri的代码是这样的

\n
class GetContentActivityResult(\n private val launcher: ManagedActivityResultLauncher<String, Uri>,\n       val uri: Uri?\n          ) {\n          fun launch(mimeType: String) {\n           launcher.launch(mimeType)\n        }\n      }\n\n@Composable\nfun rememberGetContentActivityResult(): GetContentActivityResult {\n\n var uri by rememberSaveable { mutableStateOf<Uri?>(null) }\n\n val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent(), onResult = {\n\n      uri = it\n     })\n\n return remember(launcher, uri) { GetContentActivityResult(launcher, uri) }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我在联系页面中显示图像\xc2\xa0,如下所示

\n
val getContent = rememberGetContentActivityResult() <-- to access the class of pickup files\n\nif (roomViewModel.photoUri.value.isBlank()){ <-- if no image from db display the picked image using image picker \n    getContent.uri?.let {\n              Image(\n                modifier = Modifier\n                             .align(Alignment.TopCenter)\n                             .fillMaxSize(1f),\n                         contentDescription = "UserImage",\n                         contentScale = ContentScale.Crop,\n                painter = rememberImagePainter(data = it))\n                      }\n         }else{\n\n             Image(\n               modifier = Modifier\n                            .align(Alignment.TopCenter)\n                            .fillMaxSize(1f),\n                         contentDescription = "UserImage",\n                         contentScale = ContentScale.Crop,\n                         painter = rememberImagePainter(data = roomViewModel.photoUri.value))\n            }\n    }\n\n           TextButton(\n                      onClick = { getContent.launch("image/*") }, <-- launching the class to get the image URI by defining the Mime as image/*\n                      modifier = Modifier.layoutId("changePhoto")\n            ) {\n     Text(\n         text = "Change Photo",\n        color = Color.Black)}\n
Run Code Online (Sandbox Code Playgroud)\n

主页内。没有图像选择器,我只是显示数据库中的数据,并且以这种方式显示图像

\n
@OptIn(ExperimentalCoilApi::class)\n@Composable\nfun ProfilePicture(uri : Uri, imageSize: Dp) {\n Card(\n     shape = CircleShape,\n     border = BorderStroke(\n     width = 2.dp,\n     color = Color.Red ),\n     modifier = Modifier.padding(16.dp),\n     elevation = 4.dp) {\n\n val uri2:Uri = "content://com.android.providers.media.documents/document/image%3A34".toUri() //<-- i tried to load the image this way also it didn't work.\n\n val painter = rememberImagePainter(\n                data = uri,\n                builder = {\n                placeholder(R.drawable.yara) <-- the placeholder image blinks quickly when app is loaded and then disappear...\n     }\n  )\n    Image(\n       painter = painter,\n       contentDescription = "User Image",\n       modifier = Modifier.size(imageSize) )\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

是 Uri 选择器或图像显示的问题吗?

\n

房间数据库中的其他内容正确显示(字符串)

\n

我尝试在模拟器和真实设备上使用代码,这两种情况都是相同的......

\n

我刚刚注意到的一件事...如果我使用图像选择器并选择以前选择的图像(它的 uri 在数据库中),图像会自动显示在应用程序中的其他位置,而不需要执行任何其他操作...只需选择图像并显示它而不保存它甚至......

\n

Sah*_*ous 2

嗯,我不知道该怎么做takePersistableUriPermission(),我还在学习。但我创建了一个转换器类(最长的解决方案)来使用 Uri 将其转换为位图...但我必须首先使其可绘制。我不知道如何直接从 Uri 中获取位图。

我首先更新了数据类

@Entity
data class Contact(
    @PrimaryKey()
    val id: UUID = UUID.randomUUID(),
    val name: String,
    val land_line : String,
    val mobile: String,
    val contact_photo: Bitmap
)
Run Code Online (Sandbox Code Playgroud)

TypeConverter为数据库中的位图添加了一个

    @TypeConverter
    fun fromBitmap(bitmap: Bitmap): ByteArray {
        val outputStream = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
        return outputStream.toByteArray()
    }

    @TypeConverter
    fun toBitmap(byteArray: ByteArray): Bitmap {
        return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
    }
Run Code Online (Sandbox Code Playgroud)

将值类型一直更改为 UI,并在 Util 包中创建一个转换器类,将 Uri 转换为可绘制的,然后转换为位图(我知道它看起来很愚蠢 - 任何更好的解决方案都可以接受)。

suspend fun convertToBitmap(uri: Uri, context: Context, widthPixels: Int, heightPixels: Int): Bitmap? {
    val mutableBitmap = Bitmap.createBitmap(widthPixels, heightPixels, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(mutableBitmap)
    val drawable = getDrawable(uri, context)
    drawable?.setBounds(0, 0, widthPixels, heightPixels)
    drawable?.draw(canvas)
    return mutableBitmap
}


@OptIn(ExperimentalCoilApi::class)
suspend fun getDrawable(uri: Uri, context: Context): Drawable? {
    val imageLoader = ImageLoader.Builder(context)
        .availableMemoryPercentage(0.25)
        .allowHardware(false)
        .crossfade(true)
        .build()

    val request= ImageRequest.Builder(context)
        .data(uri)
        .build()
    return imageLoader.execute(request).drawable
}
Run Code Online (Sandbox Code Playgroud)

它现在正在工作并且加载完美。我知道我的宽度和高度为 50 50 px,但无论如何这是一个测试。