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会跳转到新相册中,此时就有比较好的体验了

相关推荐
千里马学框架5 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台5 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone5 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc5 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo5 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077005 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼5 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone5 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen5 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone5 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui