As with other built-in applications, you can use the device's built-in default camera app to take pictures for use in your app. In fact, doing so is quite simple as long as your app has the proper manifest file entries and you take a few minutes to understand the options available to you, the developer.
To save your image to external storage, such as the SD card, you need permission for that:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
It's also important to let the device know that your app needs to use the camera, but declaring so in the manifest file:
<uses-feature android:name="android.hardware.camera" />
Making this declaration will prevent your app from being installed in devices that do not have a camera. This includes your AVD! To enable the camera in the virtual device, edit its settings using the AVD Manager. Under "Advanced Settings", set the front and/or back camera to something other than "None". Also, be sure to set the SD Card memory size to an amount greater than 100MB.
*Note: If your app does not use the default camera app (launched with the CAMERA action Intent), but instead handles the taking of pictures itself, then you need to set the proper permission in the manifest file:
<uses-permission android:name="android.permission.CAMERA" />
For this lesson, we will be using the default camera, so no extra permissions are needed.
The default Camera is accessed using an Intent and passing the MediaStore.ACTION_IMAGE_CAPTURE action. The intent should be launched using startActivityForResults, so that the captured image can be returned to your Activity in the onActivityResult method:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAMERA_REQUEST_CODE);
When launched this way, a low-quality image is returned as an Intent extra, and can be used as needed:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// this gets a low-quality resolution photo
Bitmap photo = (Bitmap) data.getExtras().get("data");
imageView.setImageBitmap(photo);
} else if (resultCode == RESULT_CANCELED) {
// image capture cancelled
} else {
// image capture failed
}
}
}
In order to enable the storing of higher-quality pictures, you must pass a file location as an Intent extra. Specifically, you need to add a MediaStore.EXTRA_OUTPUT extra containing the Uri of the destination file:
public void takePicture(View v){
// intent to launch default camera app
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// calls custom method that creates a file name based on the current Date
String fileName = createFileName();
// store picture to public pictures directory. This file persists if app deleted
filePath = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
+ "/" + fileName;
// or store picture to app specific folder. Files will be deleted if app is deleted
/*filePath = getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/" + fileName; */
File cameraFile = new File(filePath);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(cameraFile));
// start the image capture Intent
startActivityForResult(intent, CAMERA_REQUEST_CODE);
}
private String createFileName(){
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
return "IMG_"+ timeStamp + ".jpg";
}
Unlike the low-quality photo, the high-quality version is not delivered as an intent extra. Instead, it must be retrieved using the file path that you specified in the Intent extra:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// get the high-quality image created if intent extra used
Bitmap photo = BitmapFactory.decodeFile(filePath);
imageView.setImageBitmap(photo);
} else if (resultCode == RESULT_CANCELED) {
// image capture cancelled
} else {
// image capture failed
}
}
}
Notice that you have two options when it comes to saving your image file:
filePath = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
+ "/" + fileName
filePath = getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/" + fileName;
For more information on standard file-saving conventions, refer to the developer docs: http://developer.android.com/guide/topics/media/camera.html#saving-media