Работа с камерой на Xamarin вовлекает платформо-зависимый код, специфичный для каждой платформы. Но к счастью нам не придется писать обобщенный код, который связал бы все платформы. Благодаря классу MediaPicker из пакета Xamarin.Essentials, который по умолчанию добавляется в проект Xamarin Forms, съемка/просмотр фото/видео производятся довольно просто.
Однако первым делом для работы с камерой необходимо установить соответствующие разрешения для каждой платформы.
В проекте для Android в файл AssemblyInfo.cs в папке Properties необходимо добавить следующие строки:
// Needed for Picking photo/video [assembly: UsesPermission(Android.Manifest.Permission.ReadExternalStorage)] // Needed for Taking photo/video [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)] [assembly: UsesPermission(Android.Manifest.Permission.Camera)] // Add these properties if you would like to filter out devices that do not have cameras, or set to false to make them optional [assembly: UsesFeature("android.hardware.camera", Required = true)] [assembly: UsesFeature("android.hardware.camera.autofocus", Required = true)]
Либо добавить в файл AndroidManifest.xml, который располагается там же в папке Properties, в узел manifest следующее содержимое:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" />
Для работы на iOS требуется дополнительно добавить в файл Info.plist следующие строки:
<key>NSCameraUsageDescription</key> <string>This app needs access to the camera to take photos.</string> <key>NSMicrophoneUsageDescription</key> <string>This app needs access to microphone for taking videos.</string> <key>NSPhotoLibraryAddUsageDescription</key> <string>This app needs access to the photo gallery for picking photos and videos.</string> <key>NSPhotoLibraryUsageDescription</key> <string>This app needs access to photos gallery for picking photos and videos.</string>
Внимание! Текст между тегами <string>....</string>
следует заменить на текст, которые затем будет отображаться
пользователям в качестве информации о вашем приложении.
Для проекта UWP необходимо отметить в файле Package.appxmanifest в секции Capabilities пункты Microphone и Webcam.
MediaPicker предоставляет следующие методы для работы с камерой:
PickPhotoAsync: открывает на устройстве проводник для выбора фото
CapturePhotoAsync: открывает приложение камеры для съемки фото
PickVideoAsync: открывает проводник для выбора файла видео
CaptureVideoAsync: открывает приложение камеры для съемки видео
Все методы возвращают объект FileResult - наследник класса Stream, с которым можно работать как с файловым потоком, например, сохранить его данные в файл.
Изменим главную страницу MainPage таким образом, чтобы она имела кнопки для съемки и выбора фото и областью просмотра снятой фотографии:
using System; using System.IO; using Xamarin.Essentials; using Xamarin.Forms; namespace HelloApp { public partial class MainPage : ContentPage { Image img; Button takePhotoBtn; Button getPhotoBtn; public MainPage() { //InitializeComponent(); takePhotoBtn = new Button { Text = "Сделать фото" }; getPhotoBtn = new Button { Text = "Выбрать фото" }; img = new Image(); // выбор фото getPhotoBtn.Clicked += GetPhotoAsync; // съемка фото takePhotoBtn.Clicked += TakePhotoAsync; Content = new StackLayout { HorizontalOptions = LayoutOptions.Center, Children = { new StackLayout { Children = {takePhotoBtn, getPhotoBtn}, Orientation =StackOrientation.Horizontal, HorizontalOptions = LayoutOptions.CenterAndExpand }, img } }; } async void GetPhotoAsync(object sender, EventArgs e) { try { // выбираем фото var photo = await MediaPicker.PickPhotoAsync(); // загружаем в ImageView img.Source = ImageSource.FromFile(photo.FullPath); } catch (Exception ex) { await DisplayAlert("Сообщение об ошибке", ex.Message, "OK"); } } async void TakePhotoAsync(object sender, EventArgs e) { try { var photo = await MediaPicker.CapturePhotoAsync(new MediaPickerOptions { Title = $"xamarin.{DateTime.Now.ToString("dd.MM.yyyy_hh.mm.ss")}.png" }); // для примера сохраняем файл в локальном хранилище var newFile = Path.Combine(FileSystem.AppDataDirectory, photo.FileName); using (var stream = await photo.OpenReadAsync()) using (var newStream = File.OpenWrite(newFile)) await stream.CopyToAsync(newStream); // загружаем в ImageView img.Source = ImageSource.FromFile(photo.FullPath); } catch (Exception ex) { await DisplayAlert("Сообщение об ошибке", ex.Message, "OK"); } } } }
В обработчике первой кнопки будет производиться выбор фото. Сначала получаем само фото в виде объкта FileResult
var photo = await MediaPicker.PickPhotoAsync()
Затем загружаем его в ImageView:
img.Source = ImageSource.FromFile(photo.FullPath);
В обработчике второй кнопки делаем съемку и сохраняем фото:
var photo = await MediaPicker.CapturePhotoAsync(new MediaPickerOptions { Title = $"xamarin.{DateTime.Now.ToString("dd.MM.yyyy_hh.mm.ss")}.png" });
В данном случае в метод MediaPicker.CapturePhotoAsync передается необязательный параметр - объект MediaPickerOptions , который с помощью свойства Title позволяет настроить название файла.
Получив объект FileResult, мы можем сохранить его в качестве файла по некоторому пути. В данном случае сохраняем в локальную папку приложения:
var newFile = Path.Combine(FileSystem.AppDataDirectory, photo.FileName); using (var stream = await photo.OpenReadAsync()) using (var newStream = File.OpenWrite(newFile)) await stream.CopyToAsync(newStream);
Запустим приложение. И у нас должна отобразиться кнопка для съемки фото:
При нажатии на первую кнопку система сначала запросит, нужно ли предоставить приложению разрешения для использования камеры:
После установки разрешения нас перебросит в стандартное приложении камеры, которое имеется на устройстве. Сделаем фото, и приложение предложит сохранить сделанное фото:
После сохранения фото будет отображаться в элементе Image:
Либо мы можем нажать на вторую кнопку и выбрать в галерее необходимую фотографию для просмотра.