Android图片选择:onActivityResult未覆盖父类方法及代码过时问题求助
兄弟,我太懂你跟着两年前的视频学Android却踩坑的崩溃感了!先给你把那个错误的根源说清楚:从AndroidX普及开始,onActivityResult()这个旧方法已经被官方废弃了,现在官方推荐用Activity Result API来替代原来的startActivityForResult + onActivityResult流程。所以你的IDE会提示你“没覆盖父类方法”——因为现在的父类(比如AppCompatActivity)已经不再把这个旧方法作为标准可重写的方法,甚至直接标记成了过时。
接下来我一步步教你用现在的正确姿势实现相册选图:
第一步:确保项目用AndroidX
先检查你模块级别的build.gradle(不是项目根目录的那个),确保已经引入了AndroidX的核心依赖,尤其是Activity Result API需要的库:
dependencies { // 基础AppCompat依赖 implementation 'androidx.appcompat:appcompat:1.6.1' // Activity Result API的KTX扩展(简化代码) implementation 'androidx.activity:activity-ktx:1.7.2' implementation 'androidx.fragment:fragment-ktx:1.6.1' }
第二步:用官方内置Contract实现单图选择
AndroidX已经帮我们封装好了打开相册选图的Contract,直接用就行,不用自己写复杂的Intent逻辑:
在你的Activity或者Fragment里,先注册一个Activity Result Launcher(放在成员变量位置):
// 注册选图的Launcher,回调里处理选中的图片Uri private val pickSingleImageLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { imageUri: Uri? -> imageUri?.let { // 这里就是选中图片后的逻辑,比如显示到ImageView yourImageView.setImageURI(it) // 如果需要获取图片的真实路径、压缩图片,再在这里做后续处理 } }
然后在触发选图的地方(比如按钮点击事件),调用launch方法:
yourPickImageButton.setOnClickListener { // 传入图片的MIME类型,"image/*"表示所有图片格式 pickSingleImageLauncher.launch("image/*") }
第三步:如果需要多选图片
要是你需要一次选多张图,换用OpenMultipleDocumentsContract就行:
private val pickMultipleImagesLauncher = registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) { imageUris: List<Uri>? -> imageUris?.forEach { uri -> // 遍历处理每张选中的图片 Log.d("SelectedImage", "Uri: $uri") } } // 调用方式和单图一样 yourMultiPickButton.setOnClickListener { pickMultipleImagesLauncher.launch("image/*") }
第四步:处理相册权限(按需)
注意:从Android 10(API 29)开始,访问系统相册里的图片已经不需要READ_EXTERNAL_STORAGE权限了,除非你要访问非媒体目录的文件或者获取图片的真实文件路径。如果你的targetSdkVersion <= 28,还是要处理权限申请,结合Activity Result API可以这样做:
// 注册权限申请的Launcher private val requestStoragePermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> if (isGranted) { // 权限通过,打开相册 pickSingleImageLauncher.launch("image/*") } else { // 权限被拒,提示用户开启 Toast.makeText(this, "需要相册权限才能选择图片哦", Toast.LENGTH_SHORT).show() } } // 按钮点击时先检查权限 yourPickImageButton.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { when { ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED -> { // 已有权限,直接打开相册 pickSingleImageLauncher.launch("image/*") } shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE) -> { // 向用户解释为什么需要权限 AlertDialog.Builder(this) .setTitle("需要相册权限") .setMessage("我们需要访问你的相册来帮你选择图片") .setPositiveButton("确定") { _, _ -> requestStoragePermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE) } .setNegativeButton("取消", null) .show() } else -> { // 直接申请权限 requestStoragePermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE) } } } else { // 低于Android 6.0,不需要动态权限,直接打开相册 pickSingleImageLauncher.launch("image/*") } }
为啥旧视频的代码没用了?
Android的API迭代确实快,尤其是AndroidX推出后,很多旧API被废弃,转而用更安全、逻辑更清晰的新API替代。Activity Result API就是为了解决旧onActivityResult流程中代码分散、容易出错的问题,把请求和回调绑定在一起,维护起来更方便。
题外话:如果非要用旧的onActivityResult(非常不推荐)
要是你因为某些特殊情况必须用旧方法,得注意:你的Activity要继承AppCompatActivity,而且IDE会提示方法过时,未来的Android版本可能会彻底移除这个方法,所以真心不建议继续用。
内容的提问来源于stack exchange,提问作者tatsu

