In this recipe, we will use the default camera application in our own application and take advantage of it to save pictures. This is the opposite to the first recipe of this chapter, where we were displaying a feed coming directly from the hardware camera and bypassing the Android default application for the camera.
CameraPicture
.Main.axml
file:<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/myButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/openCamera" /> <ImageView android:src="@android:drawable/ic_menu_gallery" android:layout_width="fill_parent" android:layout_height="300.0dp" android:id="@+id/imageView1" android:adjustViewBounds="true" /> </LinearLayout>
MainActivity
class, declare a static App
class:public static class App{ public static File _file; public static File _dir; public static Bitmap bitmap; }
OnCreate()
method of your MainActivity
class so it matches the following:protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); if (IsThereAnAppToTakePictures()) { CreateDirectoryForPictures(); Button button = FindViewById<Button>(Resource.Id.myButton); _imageView = FindViewById<ImageView>(Resource.Id.imageView1); if (App.bitmap != null) { _imageView.SetImageBitmap (App.bitmap); App.bitmap = null; } button.Click += TakeAPicture; } }
MainActivity
class we previously created:private bool IsThereAnAppToTakePictures() { Intent intent = new Intent(MediaStore.ActionImageCapture); IList<ResolveInfo> availableActivities = PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly); return availableActivities != null && availableActivities.Count > 0; } private void CreateDirectoryForPictures() { App._dir = new File(Android.OS.Environment.GetExternalStoragePublicDirectory( Android.OS.Environment.DirectoryPictures), "CameraAppDemo"); if (!App._dir.Exists()) { App._dir.Mkdirs(); } }
openCamera
in the Strings.xml
file:<string name="openCamera">Open Camera</string>
TakeAPicture()
method that will be called when the user clicks on our button:private void TakeAPicture(object sender, EventArgs eventArgs) { Intent intent = new Intent(MediaStore.ActionImageCapture); App._file = new File(App._dir, String.Format("myPhoto_{0}.jpg", Guid.NewGuid())); intent.PutExtra(MediaStore.ExtraOutput, Android.Net.Uri.FromFile(App._file)); StartActivityForResult(intent, 0); }
OnActivityResult()
method to the MainActivity.cs
file:protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); // make it available in the gallery Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile); Android.Net.Uri contentUri = Uri.FromFile(App._file); mediaScanIntent.SetData(contentUri); SendBroadcast(mediaScanIntent); // display in ImageView. We will resize the bitmap to fit the display // Loading the full sized image will consume to much memory // and cause the application to crash. int height = Resources.DisplayMetrics.HeightPixels; int width = _imageView.Width ; App.bitmap = App._file.Path.LoadAndResizeBitmap (width, height); }
BitMapHelpers
:public static class BitmapHelpers { public static Bitmap LoadAndResizeBitmap(this string fileName, int width, int height) { // First we get the the dimensions of the file on disk BitmapFactory.Options options = new BitmapFactory.Options { InJustDecodeBounds = true }; BitmapFactory.DecodeFile(fileName, options); // Next we calculate the ratio that we need to resize the image by // in order to fit the requested dimensions. int outHeight = options.OutHeight; int outWidth = options.OutWidth; int inSampleSize = 1; if (outHeight > height || outWidth > width) { inSampleSize = outWidth > outHeight ? outHeight / height : outWidth / width; } // Now we will load the image and have BitmapFactory resize it for us. options.InSampleSize = inSampleSize; options.InJustDecodeBounds = false; Bitmap resizedBitmap = BitmapFactory.DecodeFile(fileName, options); return resizedBitmap; } }
First of all, the code we use here is composed of intents—see Chapter 8, Mastering Intents – A Walk-through—and, more specifically, the ActionImageCapture
intent to launch the camera application. As said in the preamble of this recipe, this time we use the default camera application instead of building our own like in the first recipe. The next action of this application is to create a directory to save the pictures taken with the application. The process of saving the picture in a file can seem a little bit tricky as we first create an empty file and add the URI of the said file to the camera intent. Finally, we intercept the OnActivityResult
action of the default camera application to make the picture available on the device's gallery and in the ImageView
instance.
3.15.202.4