文章目录

  • 1.介绍
  • 2.预览
  • 3.调试方式对比
  • 4.MediaPlugin
  • 5.权限设置
    • 5.1 iOS权限设置
    • 5.2 Android权限设置
      • 1.修改MainActivity.cs
      • 2.File Provider 配置
      • 3.配置请求权限
      • 4.其他(可选)
  • 6.实现代码
  • 7.总结
  • 8.源代码下载

1.介绍

本文基于上一篇文章《Xamarin.Forms 之我的花园-1.增删查改》的基础上实现了照片选择和拍照两个功能,这样我们就可以在添加新植物时给花花草草拍摄真实的照片。这两个功能主要通过MediaPlugin来实现,其中还会涉及到一些iOS和安卓系统下的权限获取知识。

2.预览

功能 iOS模拟器 Android模拟器
照片库
拍照
图片选择

3.调试方式对比

总结了一下VS Mac目前调试Xamarin.Forms app 尝试过以下3种方式,遇到各种问题,最后还是只能在模拟器运行了:

系统/调试方式 真机调试 Xamarin Live Player 模拟器
iOS 缺点是要99美元的开发者账号 之前安装了一个版本,编译运行时总有各种错误,而且无法更新了,官网显示还不支持了iOS?? 无法调用摄像头
Android 这里不得不吐个嘈,之前唯一用于真机的小米手机,由于更新的MIUI,发现更新后没有安装SIM卡无法通过USB进行安装,所以无奈只能在模拟器上进行了。看来以后要买张电话卡或者重新刷机才能测试了。估计除了小米手机以外,其他安卓机还好吧? 有很多限制 模拟摄像头

4.MediaPlugin

实现拍照功能我们主要用到MediaPlugin, 但同时MediaPlugin会用到PermissionsPlugin做权限检查和设置, 而Android系统下PermissionsPlugin会用到CurrentActivityPlugin来获取Current Activity,因此这三个库需要有所了解。

在MyGarden.Tutorial1(Xamarin.Froms)项目中通过NuGet搜索’Xam.Plugin.Media’来进行安装。

5.权限设置

5.1 iOS权限设置

iOS只要在MyGarden.Tutorial1.iOS项目中的Info.plist文件的Source页签中添加以下信息(String 右边的描述可以根据需要进行修改):

5.2 Android权限设置

安卓权限设置相对繁琐,需要在MyGarden.Tutorial1.Android项目中修改以下几个文件:

1.修改MainActivity.cs

在MainActivity.cs文件中添加Current Activity 插件的初始化设置和Permissions Plugin 权限请求设置。

[Activity(Label = "MyGarden", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity{protected override void OnCreate(Bundle bundle){...// 初始化 Current Activity PluginCrossCurrentActivity.Current.Init(this, bundle);...}public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults){//用于Android 6.0 之后的版本,弹出用户请求对话框,获取相应权限PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);...}}

2.File Provider 配置

1)Properties文件夹的AndroidManifest.xml

把下面内容:

 <application android:label="MyGarden.Tutorial1.Android"></application>

替换为以下内容,配置

 <application android:label="MyGarden" android:icon="@mipmap/icon" android:theme="@style/MainTheme">//File Provider配置<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></application>

2)在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>

3.配置请求权限

再次打开Properties -> AndroidManifest.xml -> Source页,添加以下内容:

 <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" />

也可以通过Properties -> AndroidManifest.xml -> Application页进行勾选对应权限,然后由系统生成上面的代码:

4.其他(可选)

在Properties文件夹下的AssembleInfo.cs文件并添加以下代码,告诉Google Play当目标设备没有以下(硬件)功能时也可以正常工作,防止app因目标设备没有以下功能时被Google Play过滤掉。

[assembly: UsesFeature("android.hardware.camera", Required = false)]
[assembly: UsesFeature("android.hardware.camera.autofocus", Required = false)]

6.实现代码

针对上一篇文章中的SavePlantPage.cs点击添加图片按钮时的方法:

async void OnLoadImagePicker(object sender, EventArgs e)
{var action = await DisplayActionSheet("从哪里添加图片?", "取消", null, "照片库", "拍照");Debug.WriteLine("你选择了: " + action);}

我们修改为以下代码:

async void OnLoadImagePicker(object sender, EventArgs e)
{var action = await DisplayActionSheet("从哪里添加图片?", "取消", null, "照片库", "拍照");switch(action){case "照片库":await SelectFromImageLibrary();break;case "拍照":await TakePhotoFromCamera();break;}
}async Task SelectFromImageLibrary()
{await CrossMedia.Current.Initialize();if (!CrossMedia.Current.IsPickPhotoSupported){await DisplayAlert("无法打开照片库", "设备不支持", "OK");return;}//检查是否有读取照片的权限,如果没有则请求一次权限var photosStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Photos);if (photosStatus != PermissionStatus.Granted){var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] { Permission.Photos });photosStatus = results[Permission.Photos];}if (photosStatus == PermissionStatus.Granted){var file = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions{PhotoSize = PhotoSize.Small,CompressionQuality = 92});if (file == null)return;AddImageControl(file.GetStream());AddPlantPhotoObject(file.Path, file.GetStream());file.Dispose();}else{await DisplayAlert("没有权限", "没有权限访问照片库", "OK");//iOS客户端时打开设置界面if (Device.RuntimePlatform == Device.iOS){CrossPermissions.Current.OpenAppSettings();}}
}async Task TakePhotoFromCamera(){await CrossMedia.Current.Initialize();if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported){await DisplayAlert("无法访问摄像头", "设备不支持", "OK");return;}//检查照相机和存储权限,没有的话进行一次请求var cameraStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Camera);var storageStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);if (cameraStatus != PermissionStatus.Granted || storageStatus != PermissionStatus.Granted){var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] { Permission.Camera, Permission.Storage });cameraStatus = results[Permission.Camera];storageStatus = results[Permission.Storage];}if (cameraStatus == PermissionStatus.Granted && storageStatus == PermissionStatus.Granted){var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions{SaveToAlbum = true //保存到照片库});if (file == null)return;Debug.WriteLine(file.AlbumPath); //公共照片库路径Debug.WriteLine(file.Path); // 私有路径AddImageControl(file.GetStream());AddPlantPhotoObject(file.AlbumPath, file.GetStream());file.Dispose();}else{await DisplayAlert("没有权限","没有权限访问摄像头或进行文件存储","OK");//iOS客户端时打开设置界面if(Device.RuntimePlatform == Device.iOS){                 CrossPermissions.Current.OpenAppSettings();}}}//添加图片控件
void AddImageControl(Stream stream)
{PhotoList.Children.Add(new Image{Source = ImageSource.FromStream(()=> { return stream; }),WidthRequest = 50,HeightRequest = 50,Aspect = Aspect.AspectFill});}//添加PlantPhoto对象到Plant.Photosvoid AddPlantPhotoObject(string path, Stream stream){if (Plant.PlantPhotos == null)Plant.PlantPhotos = new List<PlantPhoto>();Plant.PlantPhotos.Add(new PlantPhoto{Path = Path.GetFileName(path),PlantId = Plant.Id,FileStream = stream});}

7.总结

本文中,我们通过MediaPlugin在Xamarin.Froms中实现了图片选择和拍照功能。MediaPlugin目前只能选择一幅图片,实际使用中体验不是很好,要实现同时选择多张图片可以参考这个版本的MediaPlugin。

8.源代码下载

Github代码下载地址

Xamarin.Forms 之我的花园 - 2.从照片库选择图片和拍照功能相关推荐

  1. 【Xamarin】MonoTouch - iOS 使用 UIImagePickerController 打开图片库和相机选择图片修改头像...

    Application tried to present modally an active controller <UIImagePickerController: 0x7b6ff400> ...

  2. C#使用Xamarin开发可移植移动应用(1.入门与Xamarin.Forms页面),附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 什么是Xamarin? Xamarin始创于2011年,旨在使移动开发变得难以置信地迅捷和简单. Xamarin的产品简化了针对多种平台的 ...

  3. Xamarin.Forms: 无限滚动的ListView(懒加载方式)

    说明 在本博客中,学习如何在Xamarin.Forms应用程序中设计一个可扩展的无限滚动的ListView.这个无限滚动函数在默认的Xamarin.Forms不存在,因此我们需要为此添加插件.在这里我 ...

  4. Syncfusion教程:在Xamarin.Forms中创建数据输入表单 (3)

    2019独角兽企业重金招聘Python工程师标准>>> 下载Essential Studio for Xamarin最新版本 Essential Studio for Xamarin ...

  5. Xamarin.Forms探索--使用 Xamarin.Forms 来创建跨平台的用户界面

    Xamarin.Forms 是一个跨平台的.基于原生控件的UI工具包,开发人员可以轻松的创建适用于 Android,iOS 以及 Windows Phone的用户界面.与HTML 5 不同的时,Xam ...

  6. Xamarin.Forms Shell基础教程(1)

    Xamarin.Forms Shell基础教程(1) 什么是Xamarin.Forms Shell Shell是Visual Studio为Xamarin Forms提供的解决方案模版.本质上,She ...

  7. Xamarin.Forms XAML的辅助功能Code Snippet

    Xamarin.Forms XAML的辅助功能Code Snippet 在Visual Studio中,使用Code Snippet(代码片段)功能可以减少基础代码的编写量,如常见的标签.循环语句等. ...

  8. Xamarin.Forms使用Slider注意问题

    Xamarin.Forms使用Slider注意问题 Xamarin.Forms中,Slider用来构建滑块控件.其中,Minimum表示最小值,Maximum表示最大值.如果Minimum大等于1,则 ...

  9. Xamarin XAML语言教程Xamarin.Forms中构建进度条

    Xamarin XAML语言教程Xamarin.Forms中构建进度条 ProgressBar被称为进度条,它类似于没有滑块的滑块控件.进度条总是水平放置的.本节将讲解如何使用进度条. 注意:进度条在 ...

最新文章

  1. imu oracle,问一个关于IMU REDO的问题~
  2. Node.js 究竟是什么?(zz)
  3. 6 Git 分支 - 变基
  4. [css] rgba()和opacity这两个的透明效果有什么区别呢?
  5. Pytorch 神经网络训练过程
  6. 让主页或Blog日访问量增加3000
  7. c if sortable html,sortable.js中文文档
  8. Linux超简单文本编辑器:nano
  9. Redis数据结构——跳跃表-skiplist
  10. unity text不能刷新_unity自走棋制作(二)-UI制作
  11. 滴滴否认柳青计划卸任:目前正积极全面配合网络安全审查
  12. 大数据时代,海量数据处理常用思路和方法总结
  13. Vue:vue中使用layUI
  14. 实习成长之路:下层应用调不到上层方法怎么办?GoogleGuava事件上报来打配合
  15. gradle下载地址
  16. python遥感数据有偿处理_地质男转行学遥感Python——DMSP数据预处理一
  17. lg linux电视安装软件,LG电视如何安装第三方应用软件的方法教程
  18. pandas缺省值处理
  19. Ruby on Rails 教程
  20. Unity 屏幕模糊效果

热门文章

  1. 每天学一点英文:Espresso 20210811
  2. MacOS查找各Python版本的路径
  3. idea html设置字体大小,intellij idea设置(字体大小、背景)
  4. 测试开发 | 这些常用测试平台,你们公司在用的是哪些呢?
  5. 基音周期 检测 matlab,语音信号基音周期检测的matlab程序
  6. iPhoneXR为最畅销iPhone难解外界对苹果的担忧
  7. 计算机安装msvcr110.dll,安装WampServer报错 计算机中丢失MSVCR110.dll 的解决方法 | 睿客网...
  8. 辉芒微IO单片机FT60F121-RB
  9. 微信爬取过程中参数分析
  10. 有哪些电容笔值得推荐?值得买的电容笔测评