Intro
In the last post, I wrote a tutorial on how to integrate Google Maps and GPS services into a Xamarin.Forms app. This post will focus on camera integration with Xamarin.Forms. In this post I will provide code (referenced from XF Labs) that will enable your Xamarin.Forms app to take and view photos.
The following image results from this tutorial when taking a picture with an Android device:
Xamarin Labs
The code that I’m going to share was borrowed from a Xamarin.Forms Labs sample project. This sample can be found here.
Steps
- Ensure the following Nuget packages are installed on your Xamarin.Forms project and Android project:
- Xamarin.Forms
- XLabs.Forms
- XLabs.IoC
2. Update your MainActivity class to look like the following:
public class MainActivity : XFormsApplicationDroid { bool _initialized = false; protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); if (!_initialized) SetIoc(); global::Xamarin.Forms.Forms.Init(this, bundle); Xamarin.FormsMaps.Init(this, bundle); LoadApplication(new App()); } void SetIoc() { var resolverContainer = new SimpleContainer(); var app = new XFormsAppDroid(); app.Init(this); resolverContainer.Register<IDevice>(t => AndroidDevice.CurrentDevice) .Register<IDisplay>(t => t.Resolve<IDevice>().Display) .Register<IDependencyContainer>(resolverContainer) .Register<IXFormsApp>(app); Resolver.SetResolver(resolverContainer.GetResolver()); _initialized = true; } }
3. Implement the following view-model:
public class ViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; IMediaPicker _mediaPicker = null; readonly TaskScheduler _scheduler = TaskScheduler.FromCurrentSynchronizationContext(); public ViewModel() { TakePictureCommand = new DelegateCommand(async obj => await TakePicture()); SelectPictureCommand = new DelegateCommand(async obj => await SelectPicture()); } ImageSource _imageSource = null; public ImageSource ImageSource { get { return _imageSource; } set { if (_imageSource != value) { _imageSource = value; OnPropertyChanged(); } } } DelegateCommand _takePictureCommand = null; public DelegateCommand TakePictureCommand { get { return _takePictureCommand; } set { if (_takePictureCommand != value) { _takePictureCommand = value; OnPropertyChanged(); } } } DelegateCommand _selectPictureCommand = null; public DelegateCommand SelectPictureCommand { get { return _selectPictureCommand; } set { if (_selectPictureCommand != value) { _selectPictureCommand = value; OnPropertyChanged(); } } } void Setup() { if (_mediaPicker != null) return; var device = Resolver.Resolve<IDevice>(); _mediaPicker = DependencyService.Get<IMediaPicker>(); //RM: hack for working on windows phone? if (_mediaPicker == null) _mediaPicker = device.MediaPicker; } async Task TakePicture() { Setup(); ImageSource = null; await _mediaPicker.TakePhotoAsync(new CameraMediaStorageOptions { DefaultCamera = CameraDevice.Front, MaxPixelDimension = 400 }).ContinueWith(t => { if (t.IsFaulted) { var s = t.Exception.InnerException.ToString(); } else if (t.IsCanceled) { var canceled = true; } else { var mediaFile = t.Result; ImageSource = ImageSource.FromStream(() => mediaFile.Source); return mediaFile; } return null; }, _scheduler); } async Task SelectPicture() { Setup(); ImageSource = null; try { var mediaFile = await _mediaPicker.SelectPhotoAsync(new CameraMediaStorageOptions { DefaultCamera = CameraDevice.Front, MaxPixelDimension = 400 }); ImageSource = ImageSource.FromStream(() => mediaFile.Source); } catch (System.Exception ex) { Debug.WriteLine(ex.Message); } } void OnPropertyChanged([CallerMemberName]string propertyName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
4. Implement following XAML:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Pickup;assembly=Pickup" x:Class="Pickup.TakePhotoView"> <ContentPage.BindingContext> <local:ViewModel /> </ContentPage.BindingContext> <StackLayout> <Button Text="Take Picture" Command="{Binding TakePictureCommand}" /> <Button Text="Select Image from Picture Library" Command="{Binding SelectPictureCommand}" /> <Button Text="Select Video from Picture Library " Command="{Binding SelectVideoCommand}" /> <Image Source="{Binding ImageSource}" VerticalOptions="CenterAndExpand" /> <Entry Text="{Binding VideoInfo}" VerticalOptions="CenterAndExpand" /> </StackLayout> </ContentPage>
Conclusion
In conclusion, I shared some code with that will enable a developer to integrate a camera on an Android device with a Xamarin.Forms app.