Xamarin.Forms: Camera Integration

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:

CamaraIntegration

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

  1. 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.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: