弃用了 API 29 中的 "getBitmap" 函数。有什么替代代码吗?

48

我的onActivityResult无法工作,因为getBitmap已被弃用。有没有其他代码可以实现这个功能?

这里是需要更改的代码(有什么建议吗?):

val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, selectedPhotoUri)

我的工具显示getBitmap被划掉了,并显示一条消息称其已弃用。


4
被弃用并不意味着“无法使用”,它意味着该函数将在以后的版本中删除,但仍然可用。 - htafoya
14个回答

46
这对我有用,
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if(requestCode == 1 && resultCode == Activity.RESULT_OK && data != null) {

            val selectedPhotoUri = data.data
            try {
                selectedPhotoUri?.let {
                    if(Build.VERSION.SDK_INT < 28) {
                        val bitmap = MediaStore.Images.Media.getBitmap(
                            this.contentResolver,
                            selectedPhotoUri
                        )
                        imageView.setImageBitmap(bitmap)
                    } else {
                        val source = ImageDecoder.createSource(this.contentResolver, selectedPhotoUri)
                        val bitmap = ImageDecoder.decodeBitmap(source) { decoder, _, _ ->
                            decoder.setTargetSampleSize(1) // shrinking by
                            decoder.isMutableRequired = true // this resolve the hardware type of bitmap problem
                        }
                        imageView.setImageBitmap(bitmap)
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

5
它给我返回了意料之外的错误信息:“不支持的位图配置:'Hardware'”。 - Rishav Singla
2
MediaStore.Images.Media.getBitmap(contentResolver, uri) 也已经过时了。 :( - Rohit Singh
2
Rishav Singla,请使用以下代码行。imageBitmap = imageBitmap.copy(Bitmap.Config.ARGB_8888, true); - Deepak Gautam
1
这个方法在API 29级中已被弃用,官方文档。为什么要使用if(Build.VERSION.SDK_INT < 28) - Bokili Production
需要API级别28,对于较低的API,请使用旧方法。 - d-feverx
在我看来,使用旧的 Media.getBitmap 需要根据 EXIF 数据旋转图像,而使用 ImageDecoder.decodeBitmap 则不需要!我在文档中找不到任何反映这一点的内容,但已在几个设备上尝试过。有人发现了相同的问题吗? - mrrrk

22

这对我在Java中很有效

ImageDecoder.Source source = ImageDecoder.createSource(this.getContentResolver(), pictureUri);
Bitmap bitmap = ImageDecoder.decodeBitmap(source);

8
需要 API 级别为 28,那老一些的 API 级别呢? - Ahmed Maad
你可以这样做: if (Build.VERSION.SDK_INT >= 29) { val source = ImageDecoder.createSource(it.contentResolver, documentUri) ImageDecoder.decodeBitmap(source) } else { MediaStore.Images.Media.getBitmap(it.contentResolver, documentUri) } - Sikander Bakht

21

您可以使用:

private fun getCapturedImage(selectedPhotoUri: Uri): Bitmap {
    val bitmap = when {
    Build.VERSION.SDK_INT < 28 -> MediaStore.Images.Media.getBitmap(
        this.contentResolver,
        selectedPhotoUri
    )
    else -> {
        val source = ImageDecoder.createSource(this.contentResolver, selectedPhotoUri)
        ImageDecoder.decodeBitmap(source)
    }
}

10

谢谢!您有什么建议,我如何将它应用到我的现有代码中? - jaedster medina
1
@jaedstermedina 这个方法已经被弃用,但并未被移除。替代方法在答案中有提到。这与Gradle版本或Android插件无关,而是与API 29的采用相关。 - Gabriele Mariotti

6
你可以使用此代码创建位图。
Bitmap bitmap;
if (Build.VERSION.SDK_INT >= 29) {
     ImageDecoder.Source source = ImageDecoder.createSource(getApplicationContext().getContentResolver(), imageUri);
     try {
         bitmap = ImageDecoder.decodeBitmap(source);
     } catch (IOException e) {
         e.printStackTrace();
     }
} else {
     try {
     bitmap = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(), imageUri);
     } catch (IOException e) {
          e.printStackTrace();
     }
}

1
应该是 >= 28 - amrro
1
28和29都应该可以,因为旧版本在29中已被弃用,而新版本在28中推出。 - satvik choudhary

6
很明显,getBitmap API在最新的Android SDK-29上无法正常工作。因此,这对我有用。
Uri contentURI = data.getData();
try {
    imageView.setImageURI(contentURI);
} catch (Exception e) {
    e.printStackTrace();
}

如果这个方法对你们中的任何人都不起作用,请让我知道,我们可以考虑其他选项!


3

我创建了一个用于从URI加载位图的类:

public class BitmapResolver {
    private final static String TAG = "BitmapResolver";

    @SuppressWarnings("deprecation")
    private static Bitmap getBitmapLegacy(@NonNull ContentResolver contentResolver, @NonNull Uri fileUri){
        Bitmap bitmap = null;

        try {
            bitmap = MediaStore.Images.Media.getBitmap(contentResolver, fileUri);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bitmap;
    }

    @TargetApi(Build.VERSION_CODES.P)
    private static Bitmap getBitmapImageDecoder(@NonNull ContentResolver contentResolver, @NonNull Uri fileUri){
        Bitmap bitmap = null;

        try {
            bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(contentResolver, fileUri));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bitmap;
    }

    public static Bitmap getBitmap(@NonNull ContentResolver contentResolver, Uri fileUri){
        if (fileUri == null){
            Log.i(TAG, "returning null because URI was null");
            return null;
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
            return getBitmapImageDecoder(contentResolver, fileUri);
        } else{
            return getBitmapLegacy(contentResolver, fileUri);
        }
    }
   }

为了节省您的时间...


不错,现在用 Kotlin。 - htafoya
这段代码仍然无法正常工作。我认为 decodeBitmap 方法需要在一个工作线程中运行。有解决方案吗? - Gulab Sagevadiya

2

对于任何遇到“不支持的位图配置:‘Hardware’错误”的人,或者需要可变位图用于Canvas或读取像素的人,请使用以下方法:

ImageDecoder.decodeBitmap(
    ImageDecoder.createSource(context.contentResolver, uri)
) { decoder, info, source ->
    decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE
    decoder.isMutableRequired = true
}

0

ImageDecoder.createSource(this.getContentResolver(), pictureUri)

这段代码可以正常工作,但是要使用它,mindSdkVersion 至少应该为 28。


-1

你好朋友,你检查一下设备的API吗?

var Image_select: String? = null
var bitmap:Bitmap?=null

you show image set

binding?.ImAvator?.setImageURI(data!!.data)


 try {
                    val uri: Uri? = data!!.data
                    bitmap = if(Build.VERSION.SDK_INT>=29){
                        val source: ImageDecoder.Source = ImageDecoder.createSource(requireActivity()
                            .contentResolver, uri!!)
                        ImageDecoder.decodeBitmap(source)
                    } else{
                        MediaStore.Images.Media.getBitmap(requireActivity().contentResolver, uri!!)
                    }
               

                } catch (e: IOException) {
                    e.printStackTrace()
                }

上传图片时

压缩位图并发送至服务器

 fun Camparse() {
        val size = (bitmap!!.height * (812.0 / bitmap!!.width)).toInt()
        val b = Bitmap.createScaledBitmap(bitmap!!, 812, size, true)
        val by = ByteArrayOutputStream()
        b.compress(Bitmap.CompressFormat.JPEG, 100, by)
        val bytes = by.toByteArray()
        Image_select = Base64.encodeToString(bytes, 0)
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接