Therefore, this chapter will propose an implementation without additional dependencies to potentially unstable or outdated libraries. Besides a Xamarin.Forms integration with shared code we implement the actual system binding within the platform-specific projects for iOS and Android.
The shared project
First, let’s look into the shared code. We will display an Image, which will be filled with content later. So we create a member:
readonly Image image = new Image();Within the App constructor we create the page content, which is a simple button and the afore-mentioned image:
public App()
{
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
new Button {
Text = "Take a picture!",
Command = new Command(o => ShouldTakePicture()),
},
image,
},
},
};
}
The button’s click handler calls the event ShouldTakePicture. It is a public member and the platform-specific code parts will assign to it later on.
public event Action ShouldTakePicture = () => {};
Finally, we offer a public method for displaying the captured image:
public void ShowImage(string filepath)
{
image.Source = ImageSource.FromFile(filepath);
}
The Android project
On Android we modify the MainActivity. First, we define a path for the captured image file:
static readonly File file = new File(Environment.GetExternalStoragePublicDirectory(
Environment.DirectoryPictures), "tmp.jpg");
At the end of OnCreate we can use the Xamarin’s new Application.Current singleton pointing to our Appinstance and assign an anonymous event handler, which will start a new Intent for capturing an image:
(Xamarin.Forms.Application.Current as App).ShouldTakePicture += () => {
var intent = new Intent(MediaStore.ActionImageCapture);
intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(file));
StartActivityForResult(intent, 0);
};
Last but not least, our activity has to react on the resulting image. This is done by overriding the OnActivityResult method. The activity will simply push its file path to the shared ShowImage method:
(Xamarin.Forms.Application.Current as App).ShowImage(file.Path);
That’s about it! Just don’t forget to set the “Camera” and the “WriteExternalStorage” permission within “AndroidManifest.xml”!
The iOS project
For the iOS implementation we add the following code into FinishedLaunching after LoadApplication.
- Create a new image picker controller referring to the camera:
- Present the image picker controller, as soon as the ShouldTakePicture event is raised:
uiApplication.KeyWindow.RootViewController.PresentViewController(
imagePicker, true, null);
- After taking the picture, save it to the MyDocuments folder and call the shared ShowImage method:
var filepath = Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.MyDocuments), "tmp.png");
var image = (UIImage)e.Info.ObjectForKey(new NSString("UIImagePickerControllerOriginalImage"));
InvokeOnMainThread(() => {
image.AsPNG().Save(filepath, false);
(Xamarin.Forms.Application.Current as App).ShowImage(filepath);
});
uiApplication.KeyWindow.RootViewController.DismissViewController(true, null);
};
- And finally, we need to handle a cancellation of the image taking process:
Note that this is a very minimalistic implementation. For real-world applications you should add various checks, like if there is a camera available or if the image was loaded successfully.