Android 图片选择器改系统

前言

因为以前的系统图片选择器在多选的体验上太差,或者想做一些自定义的操作,所以以前一般都是使用自定义的图片选择器或者一些功能性比较强大的第三方图片选择器。但从现在起需要改成使用系统的图片选择器,为什么这么突然?因为google早已下达了最后的期限。

能看到25年的5月28就是这个的最后期限。为什么google要这么做,近年来的更新我们都知道,google一直在规范和完善权限这块领域的内容,这一操作也只是google进一步缩紧权限的操作。

那么也可以去思考一下,未来会不会进一步收缩,比如跳H5,它会不会最终弄成只允许跳自家的浏览器,或者跳其它应用会加上严苛的限制。

startActivityForResult过期

讲系统的图片选择器之前可以先预热了解一下startActivityForResult过期的问题。这个会和获取返回的图片有一定的相关。我们平时跳出应用外的页面并且需要返回数据,比如跳到相册,返回选择的相片。以前的做法一般都是通过startActivityForResult和onActivityResult去进行配合。

其中的一个核心是requestCode和resultCode,我怎么判断onActivityResult的调用是对应哪个startActivityForResult,就是用这两个code来做区分的嘛,这个注意一下,后面会考。

回归正题,现在这个方法已经过期了,如果你在项目中使用的话,你会明显发现

那么官方把这个方法过期了,自然有提供新的方法,可以参考官网 developer.android.com/training/ba...

写个Dmeo就是

scss 复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 初始化 ActivityResultLauncher
    activityResultLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                // 处理返回结果
                if (result.getResultCode() == RESULT_OK) {
                    Intent data = result.getData();
                    // 处理数据
                }
            });
}
arduino 复制代码
Intent intent = new Intent(this, SecondActivity.class); 
activityResultLauncher.launch(intent); // 启动第二个活动

这里有个需要注意的点,registerForActivityResult需要写在onCreate里面

我这里就不做演示了,那么此时你应该会发现一个问题,假如我该Activity有intent到不同页面的场景并且都有返回内容,我怎么区分此时返回的是哪个intent的,因为这个新的方式是没有requestCode去做区分的。

其实也很简单,这里的整个activityResultLauncher就可以当成一个行为的对象,如果你要跳转多个页面,那就创建多个activityResultLauncher,它内部的callback就是对应的意图

跳转系统相册进行图片选择

上面说了startActivityForResult过期了,我这里肯定直接用registerForActivityResult来实现。

kotlin 复制代码
private var imagePickerLauncher: ActivityResultLauncher<Intent>? = null

fun bindActivity(activity: AppCompatActivity, callback: (Intent?) -> Unit?) {
    this.activity = activity

    imagePickerLauncher = activity.registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            val data: Intent? = result.data
            callback.invoke(data)
        }
    }
}


fun select() {
    val intent = Intent(Intent.ACTION_PICK)
    intent.setType("image/*")
    imagePickerLauncher?.launch(intent)
}

我简单封装了一个方法,直接跳相册选择图片后返回,bindActivit需要在onCreate中调用,这个上面有重点说过。

这样看似乎是没问题,但是(Android13以下)你会发现,跳到相册里面没办法多选,只能实现单选图片的场景。那怎么进行多选呢?

Android 跳系统相册选择图片

回到最开始说的正常,联系上面的方法,既然Android提出了这个政策,而我们的旧的方法又做不到多选,那官方自然会提供新的方法给我们调用。

developer.android.com/training/da...

单选

typescript 复制代码
private var pickMultipleMedia1: ActivityResultLauncher<PickVisualMediaRequest>? = null

pickMultipleMedia1 = activity.registerForActivityResult(
    ActivityResultContracts.PickVisualMedia()
){uri ->
    callback.invoke(uri)
}

pickMultipleMedia1?.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))

多选

typescript 复制代码
private var pickMultipleMedia2: ActivityResultLauncher<PickVisualMediaRequest>? = null

pickMultipleMedia2 = activity.registerForActivityResult(
    ActivityResultContracts.PickMultipleVisualMedia(
        数量
    )
){uris ->
    if (uris.isNotEmpty()) {
        var realUris: List < Uri? > = uris
        if (uris.size > 数量){
            realUris = uris.take(数量)
        }
        callback.invoke(realUris)
    }
}

pickMultipleMedia2?.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))

多选这里里面有一步判断数量的操作,这个是和版本兼容相关的,下面会进行说明。

从这里看出,在旧版本的跳转系统相册我们是使用Intent的方法去跳转,这种方式无法适配多选的场景,而Android新提供的PickVisualMedia和PickMultipleVisualMedia能让我们实现跳转系统相册并进行单选和多选。

版本兼容

没错,PickVisualMedia和PickMultipleVisualMedia存在版本兼容的问题,在Android13以下是会打开到旧页面

可以看到这种情况下也没有多选的提示,但是当随便长按一张图片之后,就能正常打开多选的场景

但是这种多选还会存在一个问题,那就是没办法限制住图片的数量,想选多少就选多少,所以上面的代码中才会写

csharp 复制代码
        var realUris: List < Uri? > = uris
        if (uris.size > 数量){
            realUris = uris.take(数量)
        }

就是为了防止这种场景的发生,比如只能选3张图,这里选了10张,我在外边只拿前3张,当然这是我自己业务里面的策略,这里当然也可以做其它策略,比如超出就全丢掉。

而在Android13之后,PickMultipleVisualMedia会跳转到新相册中,此时就有比较好的体验了

相关推荐
REDcker1 小时前
Android WebView 版本升级方案详解
android·音视频·实时音视频·webview·js·编解码
麦兜*1 小时前
【springboot】图文详解Spring Boot自动配置原理:为什么@SpringBootApplication是核心?
android·java·spring boot·spring·spring cloud·tomcat
le1616161 小时前
Android 依赖种类及区别:远程仓库依赖、打包依赖、模块依赖、本地仓库依赖
android
lxysbly1 小时前
psp模拟器安卓版带金手指
android
云上凯歌2 小时前
02 Spring Boot企业级配置详解
android·spring boot·后端
hqiangtai2 小时前
Android 高级专家技术能力图谱
android·职场和发展
aqi002 小时前
FFmpeg开发笔记(九十七)国产的开源视频剪辑工具AndroidVideoEditor
android·ffmpeg·音视频·直播·流媒体
stevenzqzq3 小时前
Android Koin 注入入门教程
android·kotlin
炼金术3 小时前
SkyPlayer v1.1.0 - 在线视频播放功能更新
android·ffmpeg
用户276038157813 小时前
鲲鹏+昇腾:开启 AI for Science 新范式——基于PINN的流体仿真加速实践
android