Taking Pictures with Camera in Android

Taking pictures with camera follows the same approach that was used when picking an image from gallery. Basically, your activity starts the Camera application, you take a photo and save it. Once the photo is saved you will be redirected back to your app where you have the possibility to load and display the taken photo.

How Taking Pictures with Camera works

To start the Camera application, an Intent with the action ACTION_IMAGE_CAPTURE is fired. Also, this Intent is given a Uri where the picture will be saved to. The Uri basically is the location where the image will be stored on your device after the photo is taken. To get a result from the started activity, startActivityForResult() is used, instead of startActivity().
private void takePhoto() {
   Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
   intent.putExtra(MediaStore.EXTRA_OUTPUT, 
                   Uri.fromFile(getImageFile()));
   startActivityForResult(intent, TAKE_PHOTO);
}

getImageFile() returns the file where the picture content will be saved to.
private File getImageFile() {
   return new File(Environment.getExternalStorageDirectory(), 
                   "capture.png");
}
In the example above the picture will be saved in the root directory of the external storage, in a file named capture.png. Later you can use any file manager application to browse and view the photo.

Besides the Intent to start, startActivityForResult() takes a second parameter, the request code which is an integer number (TAKE_PHOTO), that will be used to identify your request in onActivityResult() callback.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   super.onActivityResult(requestCode, resultCode, data);
   FileInputStream inputStream = null; 
   // If the user finished the action
   // and the request code is your request code
   if (resultCode == RESULT_OK && requestCode == TAKE_PHOTO) {
     try {
       // Read the content of the picture into an InputStream
       inputStream = new FileInputStream(getImageFile());

       // Decode the stream and create a Bitmap from it
       Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

       // Set the image Bitmap
       imageView.setImageBitmap(bitmap);
     } catch (FileNotFoundException e) {
        Log.e("TAG", "Cant load image", e);
     } finally {
        // close resources
        closeStream(inputStream);
     }
   }
}


Below follows the complete source code of the XML layout and activity class.
The content of the main XML layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:ignore="HardcodedText" >

    <Button
        android:id="@+id/capture_image_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="6dp"
        android:text="@string/take_photo" />

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="centerCrop"
        tools:ignore="ContentDescription" />

</LinearLayout>

Full source code of the activity that manages taking and displaying the picture:
public class PhotoCameraActivity extends ActionBarActivity {

   private static final int TAKE_PHOTO = 101;
   private ImageView imageView;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_photo_camera);
 
      imageView = (ImageView) findViewById(R.id.image_view);
      Button takePhotoBtn = (Button) findViewById(R.id.take_photo);
      takePhotoBtn.setOnClickListener(new OnClickListener() {
         @Override
         public void onClick(View v) {
            takePhoto();
         }
      });
   }

   private void takePhoto() {
      Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
      intent.putExtra(MediaStore.EXTRA_OUTPUT, 
                      Uri.fromFile(getImageFile()));
      startActivityForResult(intent, TAKE_PHOTO);
   }

   private File getImageFile() {
      return new File(Environment.getExternalStorageDirectory(), 
                      "capture.png");
   }

   @Override
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      FileInputStream inputStream = null; 
      if (resultCode == RESULT_OK && requestCode == TAKE_PHOTO) {
         try {
            inputStream = new FileInputStream(getImageFile());
            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
            imageView.setImageBitmap(bitmap);
         } catch (FileNotFoundException e) {
            Log.e("TAG", "Cant load image", e);
         } finally {
            closeStream(inputStream);
         }
      }
   }

   private void closeStream(FileInputStream inputStream) {
      if (inputStream != null) {
         try {
            inputStream.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }

}

Checking the device has a camera

Although nowadays most of mobile devices come equipped with a camera, you never can be sure on what devices your android app will run. For example, not all tablets have a camera.
Therefore, before starting the camera app you have to make sure that the device has one in place.
You can check that using the hasSystemFeature(PackageManager.FEATURE_CAMERA) method of the PackageManager class.
if (isCameraAvailable()) {
   takePhoto();
} else {
   Toast.makeText(this, "This device does not have a camera", 
                  Toast.LENGTH_LONG).show();
}
// ...
private boolean isCameraAvailable() {
   return getPackageManager()
          .hasSystemFeature(PackageManager.FEATURE_CAMERA)
}

Niciun comentariu:

Trimiteți un comentariu