背景

MAUI的呈现,赋予了广阔.Net开发者开发多渠道运用的能力,MAUI 是Xamarin.Forms演变而来,可是比较Xamarin性能更好,可扩展性更强,结构更简略。可是MAUI关于渠道相关的完成并不完好。所以MASA团队开展了一个实验性项目,意在对微软MAUI的弥补和扩展

项目地址github.com/BlazorCompo…

每个功用都有独自的demo演示项目,考虑到app安装文件体积(虽然MAUI现已集成裁剪功用,可是该功用关于代码自身有影响),届时每一个功用都会以独自的nuget包的方式供给,方便测验,现在项目才刚刚开始,可是信任很快就会有能够交付的内容啦。

前言

本系列文章面向移动开发小白,从零开始进行渠道相关功用开发,演示如何参阅渠道的官方文档运用MAUI技术来开发相应功用。

介绍

Jetpack 包括一系列 Android 库,它们都采用最佳做法并在 Android 运用中供给向后兼容性

developer.android.google.cn/jetpack?hl=…

上一篇咱们是通过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() 接受 ActivityResultContractActivityResultCallback 作为参数,并回来 ActivityResultLauncher,用来发动另一个 activityActivityResultContract 界说生成成果所需的输入类型以及成果的输出类型。这些 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>

三、演示作用

MASA MAUI Plugin (九)Android相册多选照片(使用Android Jetpack套件库)

留意界面的变化,这儿是以半屏弹出的方式展示的。

假如你对咱们的 MASA Framework 感兴趣,无论是代码奉献、运用、提 Issue,欢迎联系咱们

WeChat:MasaStackTechOps QQ:7424099