MASA MAUI Plugin (九)Android相册多选照片(使用Android Jetpack套件库)
背景
MAUI的出现,赋予了广大.Net开发者开发多平台应用的能力,MAUI 是Xamarin.Forms演变而来,但是相比Xamarin性能更好,可扩展性更强,结构更简单。但是MAUI对于平台相关的实现并不完整。所以MASA团队开展了一个实验性项目,意在对微软MAUI的补充和扩展
项目地址https://github.com/BlazorComponent/MASA.Blazor/tree/feature/Maui/src/Masa.Blazor.Maui.Plugin
每个功能都有单独的demo演示项目,考虑到app安装文件体积(虽然MAUI已经集成裁剪功能,但是该功能对于代码本身有影响),届时每一个功能都会以单独的nuget包的形式提供,方便测试,现在项目才刚刚开始,但是相信很快就会有可以交付的内容啦。
前言
本系列文章面向移动开发小白,从零开始进行平台相关功能开发,演示如何参考平台的官方文档使用MAUI技术来开发相应功能。
介绍
Jetpack 包含一系列 Android 库,它们都采用最佳做法并在 Android 应用中提供向后兼容性。
上一篇我们是通过Intent实现的,今天我们用Jetpack 实现相册的多选功能。
一、实现方式
可以使用以下 activity 结果协定来启动照片选择器: 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());
这里先介绍一下registerForActivityResult
在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 的逻辑仅基于用户输入内容或其他业务逻辑也是如此。
位于 ComponentActivity 或 Fragment 中时,Activity Result API 会提供 registerForActivityResult() API,用于注册结果回调。
registerForActivityResult() 接受 ActivityResultContract 和 ActivityResultCallback 作为参数,并返回 ActivityResultLauncher,用来启动另一个 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 select ActivityResultLauncher<String> mGetContent = registerForActivityResult(new GetContent(), new ActivityResultCallback<Uri>() { @Override public void onActivityResult(Uri uri) { // Handle the returned Uri } });
这里的代码看起来很简单,我们只需要在registerForActivityResult的第二个参数中new一个ActivityResultCallback并重写onActivityResult方法即可实现获取用户操作返回的需求。但是目前在MAUI中实现并非如此简单,因为MAUI中没有定义好的ActivityResultCallback类。下面我们来编写代码。
二、代码编写
1、实现代码
在上文代码的基础上,我们继续在MainActivity.cs添加代码
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>()); } } } } }
我们创建了一个静态的ActivityResultLauncher 类型的PickMultipleMedia,并在OnCreate方法中通过RegisterForActivityResult注册,方法第一个参数类型为ActivityResultContract,我们设置了100个图片的限制,第二个参数是一个IActivityResultCallback类型的Callback。
由于默认没有提供,我们需要自己定义。 注意:我们的callback方法在继承IActivityResultCallback接口的同时,还必须显示的继承Java.Lang.Object,否则会报错。 我们仅需实现OnActivityResult方法即可,这里注意,方法的参数为Java.Lang.Object类型,有些文章会让我们将Java.Lang.Object强制转换为ActivityResult类型,然后再获取其中的文件Uri,但是经过测试目前在MAUI中不可用,转换之后永远为null。
经过多次尝试后,确定多选照片返回的类型为Android.Runtime.JavaList。 我这里通过 !p0.Equals(new Android.Runtime.JavaList()) 判断用户没有选择任何照片的场景。最后通过遍历,使用之前写好的GetImageDicFromUris方法获取所有文件的内容。
2、测试代码
我们在上文的IPhotoPickerService.cs接口中扩展一个GetImageAsync4方便我们对几种实现方式进行对比。
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>
三、演示效果
注意界面的变化,这里是以半屏弹出的方式展示的。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
GPT-3/ChatGPT复现的经验教训
作者:杨靖锋,现任亚马逊科学家,本科毕业于北大,硕士毕业于佐治亚理工学院,师从 Stanford 杨笛一教授。 译文由杨昊桐翻译,王骁修订。感谢靳弘业对第一版稿件的建议,感谢陈三星,符尧的讨论和建议。(本文经授权后由OneFlow发布。原文:https://jingfengyang.github.io/gpt) 为什么所有公开的对 GPT-3 的复现都失败了?我们应该在哪些任务上使用 GPT-3.5 或 ChatGPT? 对于那些想要复现一个属于自己的 GPT-3 或 ChatGPT 的人而言,第一个问题是关键的。第二个问题则对那些想要使用它们的人是重要的(下文提到 GPT-3,主要是指 GPT-3.5 或 InstructGPT 的最新版本,除了一些指向 GPT-3 原文的情况)。 这篇博客 包括我在仔细重新检查了一系列文章的细节之后给出的总结,以及对上面两个问题我个人的思考。这些文章包括且不限于:GPT-3, PaLM, BLOOM, OPT, FLAN-T5/PaLM, HELM 等。均为个人意见,仅供参考。如果您有更可靠的参考资料或者更实际的经验,欢迎指正。 1 为什...
- 下一篇
基于头肩部检测的过线客流统计
摘要:通过本教程,我们学习了另一类客流统计应用——过线客流统计,通常用于室内出入口,摄像头会架设在高处俯拍,使用头肩部检测可以减少人与人之间的遮挡。 本文分享自华为云社区《客流分析之基于头肩部检测的过线客流统计》,作者:HiLens_feige 。 1.基于头肩部检测的过线客流统计 除了划区域客流统计之外,另一类常见的客流统计场景是过线客流统计,本文介绍基于头肩部检测的过线客流统计技能:采用头肩部检测人形并进行跟踪,当头肩部中心点跨过事先划定的线段时,增加客流计数;过线前后的人形将使用不同颜色的框表示,画面中也会实时显示客流数量。 准备工作 本文将使用华为云ModelArts进行人形检测模型的训练,并使用ModelBox框架进行应用开发,使用前开发者需要完成如下准备工作: 参考此教程完成设备的注册; 参考此教程完成ModelBoxSDK的安装。 2.技能开发 这个应用对应的ModelBox版本已经做成模板放在华为云OBS中,可以用sdk中的solution.bat工具下载,接下来我们给出该应用在ModelBox中的完整开发过程: 1)下载模板 执行.\solution.bat -l可看...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS8编译安装MySQL8.0.19
- CentOS7,CentOS8安装Elasticsearch6.8.6