Taking screenshots with the camera

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.

Getting ready

Create a new solution named CameraPicture and open it in Xamarin Studio.

How to do it...

  1. Create another project in the solution created in the first recipe and name it CameraPicture.
  2. Add the following code into your 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>
  3. In the MainActivity class, declare a static App class:
    public static class App{
      public static File _file;
      public static File _dir;
      public static Bitmap bitmap;
    }
  4. Modify the 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;
      }
    }
  5. Add the following code (reference http://developer.xamarin.com/recipes/android/other_ux/camera_intent/take_a_picture_and_save_using_camera_app/) to the 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();
      }
    }
  6. Add a resource named openCamera in the Strings.xml file:
    <string name="openCamera">Open Camera</string>
  7. Implement the 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);
    }
  8. Add an 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);
    }
  9. Create a static class named 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;
      }
    }
  10. Run your application. You should see something similar to the following screenshot where you can see a picture of my lab at Concordia University taken with the webcam that replaces the camera in the Android emulator:
    How to do it...

How it works...

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.

See also

See also the next recipe to create beautiful animations in your applications, and the links mentioned in the previous recipe for more information.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.202.4