背景
前言
本系列文章面向移动开发小白,从零开始进行平台相关功能开发,演示如何参考平台的官方文档使用MAUI技术来开发相应功能。
介绍
Jetpack 包含一系列 Android 库,它们都采用最佳做法并在 Android 应用中提供向后兼容性。
https://developer.android.google.cn/jetpack?hl=zh-cn
上一篇我们是通过Intent实现的,今天我们用Jetpack 实现相册的多选功能。
一、实现方式
PickVisualMedia,用于选择单张图片或单个视频。
PickMultipleVisualMedia,用于选择多张图片或多个视频。
我们的需求是可以多选照片,我们主要介绍PickMultipleVisualMedia的使用方法。
我们先看一下JAVA的示例代码
JAVA代码// Registering Photo Picker activity launcher with multiple selects (5 max in this example)ActivityResultLauncher<PickVisualMediaRequest> pickMultipleMedia = registerForActivityResult(new PickMultipleVisualMedia(5), uris -> { // Callback is invoked after the user selects media items or closes the // photo picker. if (!uris.isEmpty()) { Log.d("PhotoPicker", "Number of items selected: " + uris.size()); } else { Log.d("PhotoPicker", "No media selected"); }});// For this example, launch the photo picker and allow the user to choose images// and videos. If you want the user to select a specific type of media file,// use the overloaded versions of launch(), as shown in the section about how// to select a single media item.pickMultipleMedia.launch(new PickVisualMediaRequest.Builder() .setMediaType(PickVisualMedia.ImageAndVideo.INSTANCE) .build());
在Android中启动另一个 activity(无论是您应用中的 activity 还是其他应用中的 activity)不一定是单向操作。我们需要获取activity的返回结果。这里我们就是启动了相册,并获取用户选取照片的返回结果。其他例如打开相机获取拍照结果,打开通讯录获取联系人结果都是具体的应用场景。
虽然所有 API 级别的 Activity 类均提供底层 startActivityForResult() 和 onActivityResult() API,但Android官方强烈建议使用 AndroidX Activity 和 Fragment 中引入的 Activity Result API。
Activity Result API 提供了用于注册结果、启动结果以及在系统分派结果后对其进行处理的组件。
在启动 activity 以获取结果时,可能会出现您的进程和 activity 因内存不足而被销毁的情况;如果是使用相机等内存密集型操作,几乎可以确定会出现这种情况。
因此,Activity Result API 会将结果回调从您之前启动另一个 activity 的代码位置分离开来。由于在重新创建进程和 activity 时需要使用结果回调,因此每次创建 activity 时都必须无条件注册回调,即使启动另一个 activity 的逻辑仅基于用户输入内容或其他业务逻辑也是如此。
ActivityResultContract 定义生成结果所需的输入类型以及结果的输出类型。这些 API 可为拍照和请求权限等基本 intent 操作提供默认协定。当然也可以创建自己的自定义协定。
ActivityResultCallback 是单一方法接口,带有 onActivityResult() 方法,可接受 ActivityResultContract 中定义的输出类型的对象:
JAVA代码// GetContent creates an ActivityResultLauncher<String> to allow you to pass// in the mime type you'd like to allow the user to selectActivityResultLauncher<String> mGetContent = registerForActivityResult(new GetContent(), new ActivityResultCallback<Uri>() { @Override public void onActivityResult(Uri uri) { // Handle the returned Uri }});
二、代码编写
1、实现代码
public class MainActivity : MauiAppCompatActivity { internal static MainActivity Instance { get; private set; } internal static ActivityResultLauncher PickMultipleMedia { get; private set; } public TaskCompletionSource<Dictionary<string, string>> PickImageTaskCompletionSource { set; get; } protected override void OnCreate(Bundle savedInstanceState) { Instance = this; PickMultipleMedia = Instance.RegisterForActivityResult(new ActivityResultContracts.PickMultipleVisualMedia(100), new ActivityResultCallback()); base.OnCreate(savedInstanceState); } private class ActivityResultCallback : Java.Lang.Object, IActivityResultCallback { public void OnActivityResult(Java.Lang.Object p0) { if (!p0.Equals(new Android.Runtime.JavaList())) { var list = (Android.Runtime.JavaList)p0; if (!list.IsEmpty) { var uris = list.Cast<Uri>().ToList(); var fileList = Instance.GetImageDicFromUris(uris); Instance.PickImageTaskCompletionSource.SetResult(fileList); } else { Instance.PickImageTaskCompletionSource.SetResult(new Dictionary<string, string>()); } } } } }
注意:我们的callback方法在继承IActivityResultCallback接口的同时,还必须显示的继承Java.Lang.Object,否则会报错。
2、测试代码
public class AndroidPhotoPickerService : IPhotoPickerService { ... public Task<Dictionary<string, string>> GetImageAsync4() { MainActivity.PickMultipleMedia.Launch(new PickVisualMediaRequest.Builder() .SetMediaType(ActivityResultContracts.PickVisualMedia.ImageAndVideo.Instance).Build()); MainActivity.Instance.PickImageTaskCompletionSource = new TaskCompletionSource<Dictionary<string, string>>(); return MainActivity.Instance.PickImageTaskCompletionSource.Task; } }
这里使用的方法非常简单,参考上面JAVA的写法即可
JAVA代码pickMultipleMedia.launch(new PickVisualMediaRequest.Builder() .setMediaType(PickVisualMedia.ImageAndVideo.INSTANCE) .build());
在Index.razor中添加一个MListItem
<MList> ... <MListItem OnClick="GetImageAsync4"> <MListItemContent> <MListItemTitle>Jetpack-PickMultipleVisualMedia</MListItemTitle> </MListItemContent> </MListItem></MList>
三、演示效果
注意界面的变化,这里是以半屏弹出的方式展示的。