Android Image Capture: Custom API and System Intent Approaches
Android offers two primary approaches for capturing images: delegating to a system camera application via an implicit Intent, or directly controlling the hardware using the Camera API.
Deleagting to the system camera application involves constructing an Intent with the ACTION_IMAGE_CAPTURE action. The system then launches the default camera app, handles the user interaction, and returns the captured image to the calling activity.
Direct API control involves opening the camera hardware, configuring parameters, and triggering the capture programmatically. This provides granular control but requires careful management of the camera lifecycle, including releasing the resource when finished.
Activity Implementation
The following PhotoCaptureActivity demonstrates both techniques. Two separate buttons trigger the respective methods. The triggerSystemCamera method launches the external app, saving the result to a local cache file. The triggerDirectCamera method opens the device camera, takes a picture, and decodes the raw byte array into a Bitmap.
package com.example.imaging;
import java.io.File;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.widget.ImageView;
public class PhotoCaptureActivity extends Activity {
private ImageView displayView;
private Camera deviceCamera;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.capture_layout);
displayView = (ImageView) findViewById(R.id.photo_display);
}
public void triggerSystemCamera(View v) {
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File outputFile = new File(getExternalCacheDir(), "snapshot.jpg");
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outputFile));
startActivityForResult(captureIntent, 100);
}
public void triggerDirectCamera(View v) {
deviceCamera = Camera.open();
deviceCamera.takePicture(null, null, new PictureCallback() {
@Override
public void onPictureTaken(byte[] rawData, Camera cam) {
Bitmap capturedImage = BitmapFactory.decodeByteArray(rawData, 0, rawData.length);
displayView.setImageBitmap(capturedImage);
cam.release();
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent resultData) {
super.onActivityResult(requestCode, resultCode, resultData);
if (resultCode == RESULT_OK && resultData != null) {
Bitmap thumbnail = resultData.getParcelableExtra("data");
if (thumbnail != null) {
displayView.setImageBitmap(thumbnail);
}
}
}
@Override
protected void onPause() {
super.onPause();
if (deviceCamera != null) {
deviceCamera.release();
deviceCamera = null;
}
}
}
Layout Configuration
The interface contains two buttons mapped to the respective click handlers, along with an ImageView to render the resulting Bitmap.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_system_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="triggerSystemCamera"
android:text="Launch System Camera" />
<Button
android:id="@+id/btn_direct_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="triggerDirectCamera"
android:text="Direct Camera API" />
<ImageView
android:id="@+id/photo_display"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Manifest Permissions
Accessing the camera hardware requires explicit permissions and feature declarations in the AndroidManifest.xml.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.imaging">
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:label="Image Capture App">
<activity
android:name=".PhotoCaptureActivity"
android:label="Photo Capture">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>