本文主要介绍在Xamarin.Forms中实现对相机与相册的操作,其中需要引用到的插件是 Xam.Plugin.Media
1.插件引用
首先在项目中引入Xam.Plugin.Media
的插件,在这里以 .Net Standaed
为例,三个项目下面都要引用,且每次更新都需要保持版本一致,如图:
PS:几年前开发的时候,那个时候还是Xamarin.Forms2.0,那个时候Xam.Plugin.Media插件的不同版本依赖于不同版本的Xamarin.Forms版本,当然了肯定是两者中有其一更新不及时所导致的,不过现在Xamarin.Forms3.0以来两者都相对稳定。
2.权限配置
第一步完成后先别急着码代码,有些事先做在前面,IOS与Andoird当中还有一些特定的权限需要处理。
2.1 IOS:
IOS的权限配置相对简单,只需要在IOS项目中选择Info.plist
文件打开后添加对应的“相机权限”和“相册权限”的即可如图:
后面是对当前权限使用的说明,会在用户首次操作的时候提示给用户,比如“当前应用需要在**操作时使用您的相机/相册”
2.2 Android:
Android的权限配置步骤相对较多
-
1.MainActivity.cs
由于此插件使用
Current Activity Plugin
来访问当前的Android Activity
,所以需要在OnCreate
方法中添加Current Activity
插件的初始化设置,代码如下:CrossCurrentActivity.Current.Init(this, bundle);
紧接着在
MainActivity
中添加Permissions Plugin
权限请求设置,代码如下:public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults) { Plugin.Permissions.PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults); }
-
AndroidManifest.xml
配置请求权限(也可以通过手动勾选添加)<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_USER_DICTIONARY" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
配置文件中还需要进行相应的设置,在
<application>
节点下方添加以下代码<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data> </provider>
-
在
Resources
文件夹中创建一个xml
文件夹,然后创建一个file_paths.xml
的文件:<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="my_images" path="Pictures" /> <external-files-path name="my_movies" path="Movies" /> </paths>
-
AssembleInfo.cs
在我们添加了上述的权限后,Google Play会自动过滤掉没有特定硬件的设备,为了防止出现这种情况,我们需要告诉Google当前设备在没有以下硬件功能时也可以正常工作,代码如下:[assembly: UsesFeature("android.hardware.camera", Required = false)] [assembly: UsesFeature("android.hardware.camera.autofocus", Required = false)]
3.API使用
在调用插件进行拍照或者视频之前,需要先检查相机时候存在以及当前手机是否支持拍照和视频。可以通过调用CrossMedia.Current
以获取对API的访问权限:
权限:
/// <summary>
/// 必须在检查下面的属性之前调用以初始化所有相机组件
/// </summary>
/// <returns>If success</returns>
Task<bool> Initialize();
/// <summary>
/// 获取设备上是否有可用的摄像头
/// </summary>
bool IsCameraAvailable { get; }
/// <summary>
/// 获取是否能够拍摄设备上支持的照片
/// </summary>
bool IsTakePhotoSupported { get; }
/// <summary>
/// 获取设备是否支持选择照片的功能
/// </summary>
bool IsPickPhotoSupported { get; }
/// <summary>
/// 获取设备是否支持拍摄视频的能力
/// </summary>
bool IsTakeVideoSupported { get; }
/// <summary>
/// 获取设备是否支持选择视频的功能
/// </summary>
bool IsPickVideoSupported { get; }
照片:
/// <summary>
/// 从相册中挑选照片
/// </summary>
/// <param name="options">选择照片媒体选项</param>
/// <returns>媒体文件,如果取消则为null</returns>
Task<MediaFile> PickPhotoAsync(PickMediaOptions options = null);
/// <summary>
/// 使用相机拍摄照片
/// </summary>
/// <param name="options">相机媒体选项</param>
/// <returns>照片的媒体文件,如果取消则为null</returns>
Task<MediaFile> TakePhotoAsync(StoreCameraMediaOptions options);
视频:
/// <summary>
/// 从相册中挑选视频
/// </summary>
/// <returns>视频的媒体文件,如果取消则为null</returns>
Task<MediaFile> PickVideoAsync();
/// <summary>
/// 使用相机拍摄视频
/// </summary>
/// <param name="options">视频媒体选项</param>
/// <returns>视频的媒体文件,如果取消则为null</returns>
Task<MediaFile> TakeVideoAsync(StoreVideoOptions options);
4.代码实现(以拍照为例)
takePhoto.Clicked += async (sender, args) =>
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
DisplayAlert("No Camera", ":( No camera available.", "OK");
return;
}
var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "Sample",
Name = "test.jpg"
});
if (file == null)
return;
await DisplayAlert("File Location", file.Path, "OK");
image.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
return stream;
});
};
5.完善
在完成以上功能后,发现一个小细节,那就是调用IOS相机/相册的时候,相关操作文字全是英文,当然了这并没有什么不好,还高大上一点,但实际项目中碰到客户不懂中文,那只能乖乖改了(>.<)…
实际操作起来很简单,还是权限的问题,在IOS项目下的info.plist
文件中添加Localized resources can be mixed
,对应的值是Boolean
类型的,选Yes就可以了
6.总结
当前文章对Xamarin实现的移动端Media相关功能大致描述了一下,当然有关Media相关的操作肯定不止这一种实现方法,你也可以分平台实现最后通过接口统一调用,这样可以更完美的实现,不过这就相对复杂多了,还是需要选择最适合当前项目的方法来实现。
7.源码
最后提供一下你们期待已久的源码
GitHub:https://github.com/jamesmontemagno/MediaPlugin