Anda di halaman 1dari 46


L. Grewe
Android Devices have cameras

What can you do with a camera?

Must ask permission to use Android
Camera or its features
Examples (first one is the one we use)PUT in
Manifest.xml file
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="" />
<uses-feature android:name="" />
Two Optionsfor coding

OPTION 1) Create Intent to existing Camera App---

just to take quick picture and get file returning to
your appcamera picture controls not part of your
OPTION 2) Create your own camera controls inside
your app and take a picture
Some Classes involved..
Option 1: via Intent to existing Camera App
Intent An intent action type of MediaStore.ACTION_IMAGE_CAPTURE or
MediaStore.ACTION_VIDEO_CAPTURE can be used to capture

Option 2: via Your own controls and Interface HAS 2 Options

Before API 21
Camera This class is the primary API for controlling device cameras. This class is used
to take pictures or videos when you are building a camera application..
SurfaceView This class is used to present a live camera preview to the user.
MediaRecorder This class is used to record video from the camera.
Released with API 21
Newer android.hardware.camera2
Option 1: Create Intent to call existing
Camera App
Existing Android Camera App takes picture and
return then to your application with data stored
into a file that your app can access

--uses Intents and existing Camera App to minimize

code you have to write just to get a picture (or
video) taken.
--good when you dont need camera controls , etc.
to be part of your apps interface
Option 1: Intent to existing Camera
Newer with later Android SDK version
Opton 1: Intent to existing Camera
App Steps
1. Compose a Camera Intent - Create an Intent that requests an image or
video, using one of these intent types:
MediaStore.ACTION_IMAGE_CAPTURE - Intent action type for requesting an image
from an existing camera application.
MediaStore.ACTION_VIDEO_CAPTURE - Intent action type for requesting a video from
an existing camera application.
2. Start the Camera Intent - Use the startActivityForResult() method to
execute the camera intent. After you start the intent, the (already
existing) Camera application user interface appears on the device screen
and the user can take a picture or video.
3. Receive the Intent Result - Set up an onActivityResult() method in your
application to receive the callback and data from the camera intent.
When the user finishes taking a picture or video (or cancels the
operation), the system calls this method. This is like a callback function
Option 1: with/ existing Camera
Lets look at some code
Remember: you must ask for permission in the Manifest xml file!!!
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=""
<uses-sdk android:minSdkVersion="12" />
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-feature android:name="" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".CameraSimpleActivity"
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
package grewe.example.Camera.Simple;
import android.os.Bundle;
import android.provider.MediaStore;
import android.content.Intent;
import android.os.Environment;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.widget.Toast;

public class CameraSimpleActivity extends Activity {

//variables to determine Image versus video
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
private Uri fileUri; //location of where will store image or video
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
OPTION1: method to
create and start Intent
/** Called when the activity is first created. --- CREATES INTENT AND STARTS IT */
public void onCreate(Bundle savedInstanceState) {

//get the picture taken by external existing Camera App right

//away at start...could do instead as a result of Event handling
// create Intent to take a picture and return control to the calling application
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //Create Intent

//setup File URL for location for image

fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

// start the image capture Intent

startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);

OPTION1: callback method
when Camera Intent done

//METHOD to Get Intents Recieved --in this case when camera app done
// will put message in TextView on main apps interface if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
@Override if (resultCode == RESULT_OK) {
protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Video captured and saved to fileUri specified in the Intent
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) { Toast.makeText(this, "Video saved to:\n" +
if (resultCode == RESULT_OK) {
data.getData(), Toast.LENGTH_LONG).show();
// say that we saved image } else if (resultCode == RESULT_CANCELED) {
TextView t = (TextView)findViewById(;
t.setText("Success"); // User cancelled the video capture
} else {
} else if (resultCode == RESULT_CANCELED) {
// User cancelled the image capture // Video capture failed, advise user
TextView t = (TextView)findViewById(;
t.setText("Camera Cancelled");
} else { }
// Image capture failed, advise user
TextView t = (TextView)findViewById(;
methods for getting File URL
//METHODS to handle file storage
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){ // Create a media file name
return Uri.fromFile(getOutputMediaFile(type)); String timeStamp = new
} SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

/** Create a File for saving an image or video */ File mediaFile;

private static File getOutputMediaFile(int type){ if (type == MEDIA_TYPE_IMAGE){

// To be safe, you should check that the SDCard is mounted mediaFile = new File(mediaStorageDir.getPath() + File.separator
// using Environment.getExternalStorageState() before doing this.
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
File mediaStorageDir = new
File(Environment.getExternalStoragePublicDirectory( mediaFile = new File(mediaStorageDir.getPath() + File.separator
Environment.DIRECTORY_PICTURES), "MyCameraApp");
"VID_"+ timeStamp + ".mp4");
// This location works best if you want the created images to be shared
} else {
// between applications and persist after your app has been uninstalled.
return null;
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
return mediaFile;
Log.d("MyCameraApp", "failed to create directory");
return null;
OPTION 1: Lets run it
OPTION 1: Running results
Suppose you want the image data
Option 1 load the Image from the File you specified
Option 2 the Intent returned from using Camera
App has a small version of the image bitmap that
was taken you can grab directly
Option 1: Loading (regular size)
image from saved File
private void setPic() {
// Get the dimensions of the View - NOTE: assumes the Activity has a ImageView object mImageView
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();

// Get the dimensions of the bitmap NOTE: assumes mCurrentPhotoPath is location of image you took
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;

// Determine how much to scale down the image

int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;

Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);

Option 2: getting small image stored directly in
Intent returned from Camera App
Alter your onActivityResults method
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Good Only
for small
if (resultCode == RESULT_OK) {
Icon type Images
//The Intent has the image call a method passing this Intent
handleSmallCameraPhoto(Intent intent);
}}//****rest of method***
//assume Activity as an ImageView object called
//mImageView and an ImageBitmap object to store data called mImageBitmap
private void handleSmallCameraPhoto(Intent intent) {
Bundle extras = intent.getExtras();
mImageBitmap = (Bitmap) extras.get("data");
Option 2: have your application create
code to control camera
OPTION 2: Have application itself create
controls to take picture (dont leave APP)
An app that takes a create the
interface to take picture and show preview,etc.
(does not use existing app).

Requires use of API classes like Camera,

More complicated but, you get
moreappropriate for apps that need it
OPTION 2: Camera inside your
app..Classes involved
Camera This class is the primary API for controlling
device cameras. This class is used to take pictures
or videos when you are building a camera
application.. (if device or emulator has multiple
cameras uses first rear facing camera can find)
SurfaceView This class is used to present a live
camera preview to the user.
MediaRecorder This class is used to record video
from the camera.
OPTION2: some devices have
more than one camera
Android devices can have multiple cameras, for
example a back-facing camera for photography
and a front-facing camera for video calls. Android
2.3 (API Level 9) and later allows you to check the
number of cameras available on a device using the
Camera.getNumberOfCameras() method.
OPTION 2: Camera inside
AppThe Steps
1. Detect and Access Camera - Create code to check for the existence of
cameras and request access.
2. Create a Preview Class - Create a camera preview class that extends
SurfaceView and implements the SurfaceHolder interface. This class
previews the live images from the camera.
3. Build a Preview Layout - Once you have the camera preview class,
create a view layout that incorporates the preview and the user interface
controls you want.
4. Setup Listeners for Capture - Connect listeners for your interface controls
to start image or video capture in response to user actions, such as
pressing a button.
5. Capture and Save Files - Setup the code for capturing pictures or videos
and saving the output.
6. Release the Camera - After using the camera, your application must
properly release it for use by other applications.
OPTION 2: STEP 1--detect if
/** Check if this device has a camera */private boolean checkCameraHardware(Context context) {
// this device has a camera
return true;
} else {
// no camera on this device
return false;

//above uses PackageManager.hasSystemFeature() method to see if camera available on device

OPTION 2: STEP 1 - access Camera
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c =; // attempt to get a Camera instance
catch (Exception e){
// Camera is not available (in use or does not exist)
return c; // returns null if camera is unavailable

//More than 1 Camera?: On devices running Android 2.3 (API Level 9) or higher, you can
access specific cameras using The example code above will access the first,
back-facing camera on a device with more than one camera.
OPTION 2: STEP 1 (optional)
check camera capabilities
using the Camera.getParameters() method and
checking the returned Camera.Parameters object
for supported capabilities.
When using API Level 9 or higher, use the
Camera.getCameraInfo() to determine if a camera
is on the front or back of the device, and the
orientation of the image.
OPTION 2: Step 2- create Preview
Users (usually) must be able to see what the device
camera sees.
SurfaceView =can display the live image data
coming from a camera
THE CODE next:
how to create basic camera preview class that can be
included in a View layout.
implements SurfaceHolder.Callback in order to capture
the callback events for creating and destroying the
view, which are needed for assigning the camera
preview input.
OPTION 2- Step 2 Preview
Interface code
public CameraPreview(Context context, Camera camera) {
package grewe.examples.Camera.InApp;
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
import android.view.Surface;
// underlying surface is created and destroyed.
import android.view.SurfaceHolder;
mHolder = getHolder();
import android.view.SurfaceView;
import android.hardware.Camera;
// deprecated setting, but required on Android versions prior to 3.0
import android.content.*;
import android.util.Log;

public void surfaceCreated(SurfaceHolder holder) {

// The Surface has been created, now tell the camera
//where to draw the preview.
public class CameraPreview extends SurfaceView implements
try {
SurfaceHolder.Callback {
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " +
private SurfaceHolder mHolder; e.getMessage());
private Camera mCamera; }
OPTION 2- Step 2 Preview
Interface code
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
if (mCamera != null)
// Call stopPreview() to stop updating the preview surface.
mCamera.stopPreview(); // make any resize, rotate or reformatting changes here

// start preview with new settings
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { try {
// If your preview can change or rotate, take care of those events here. mCamera.setPreviewDisplay(mHolder);
// Make sure to stop the preview before resizing or reformatting it. mCamera.startPreview();

if (mHolder.getSurface() == null){ } catch (Exception e){

// preview surface does not exist // Log.d(TAG, "Error starting camera preview: " +
// stop preview before making changes
try {
} catch (Exception e){
// ignore: tried to stop a non-existent preview
OPTION 2: Step 2 more on
orientation of App
Note: A camera preview does not have to be in
landscape mode. Starting in Android 2.2 (API Level
8), you can use the setDisplayOrientation() method to
set the rotation of the preview image. In order to
change preview orientation as the user re-orients the
phone, within the surfaceChanged() method of your
preview class, first stop the preview with
Camera.stopPreview() change the orientation and
then start the preview again with
OPTION 2: Step 2- attaching Preview
Interface to Layout in App
Edit the appropriate XML layout file.
Here showing the XML file---add a FrameLayout to contain the Preview.
Also add a button to later trigger image capture
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=""
android:layout_height="fill_parent" >
android:layout_weight="1 />
android:layout_gravity="center />
OPTION 2: Step 3- layout of
preview interface
On most devices, the default orientation of the
camera preview is landscape.
This previous code layout specifies a horizontal
(landscape) layout
Change Manifest file so app is in landscape.
android:screenOrientation="landscape" >
OPTION 2: Step 3- add preview
into Frame Layout created
In the activity for your camera view, add your
preview class to the FrameLayout element shown in
the example above
public class CameraActivity extends Activity {

private Camera mCamera;

private CameraPreview mPreview;

public void onCreate(Bundle savedInstanceState) {

// Create an instance of Camera

mCamera = getCameraInstance();

// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(id.camera_preview);
OPTION 2: Step 4&5 code to do capture
---trigger and handling
set up listeners for your user interface controls to
respond to a user action by taking a picture.
Camera.takePicture() = takes picture,
3 parameters which receive data from the camera.
To get data in a JPEG format, you must implement an
Camera.PictureCallback interface to receive the image
data and write it to a file.
OPTION 2: Step 4&5 event handling
when button hit this is callback after
picture taken ---store to file
Add code to main Application Activity class
This is private variable of this class
private PictureCallback mPicture = new PictureCallback() {

public void onPictureTaken(byte[] data, Camera camera) {

File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);

if (pictureFile == null){
Log.d(TAG, "Error creating media file, check storage permissions: " +

try {
FileOutputStream fos = new FileOutputStream(pictureFile);
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
OPTION2- Step 4&5 registering
event handler to a button
Trigger capturing an image by calling the
Camera.takePicture() method. The following
example code shows how to call this method from a
button View.OnClickListener.
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
new View.OnClickListener() {
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);//see previous page code
//callback is mPicture !!!!
OPTION2 Step 6 Release the
Caution: Remember to release the Camera object
by calling the Camera.release() when your
application is done using it! For information about
how to release the camera, see Releasing the
OPTION 2: Steps
1) Create simple interface with a button that will
trigger taking the picture
App Interface --- button
Add button
The Main Application (Activity) class
import; //loads interface stored in main.xml of layout directory
import android.content.Intent; setContentView(R.layout.main);
import; Button cameraButton = (Button) findViewById(;
import android.os.Bundle; //setups button to have even so that it creates an Activity
import android.util.Log; //of instance photoshoot.class and start it as an Activity
import android.view.View; cameraButton.setOnClickListener( new OnClickListener(){
import android.view.View.OnClickListener; public void onClick(View v ){
import android.widget.Button; Intent i = new Intent(cameralab2.this, photoshoot.class);
import android.widget.ImageView; startActivityForResult(i,CAMERALAB2);
public class cameralab2 extends Activity { });
/** Called when the activity is first created. */
final int CAMERALAB1=1; }
public void onCreate(Bundle savedInstanceState) {
The Main Application (Activity) class
Here setting up the protected void onActivityResult(int requestCode, int resultCode, Intent
data) {

ImageView and setting if (requestCode== CAMERALAB1 && resultCode ==


bitmap to image Log.v("Result","Result:"+data.toURI());

associated with Intent Bundle extras = data.getExtras();

passed to Bitmap b = (Bitmap) extras.get("data");

else if (requestCode== CAMERALAB2 && resultCode ==
Bundle extras = data.getExtras();
String imageurl = extras.getString("url");
Uri imgUri = Uri.parse(imageurl);
PhotoShoot class

First the imports. Activity and implements

import android.content.Intent; SurfaceHolder.Callback
import; public class photoshoot extends Activity implements SurfaceHolder.Callback
import; {
import; private static final String TAG = "photoshoot";
import; Camera mCamera;
import android.hardware.Camera; boolean mPreviewRunning = false;
import android.os.Bundle; byte[] tempdata;
import android.os.Debug; private SurfaceView mSurfaceView;
import android.provider.MediaStore.Images; private SurfaceHolder mSurfaceHolder;
import android.util.Log; public void onCreate(Bundle icicle)
import android.view.SurfaceHolder; {
import android.view.SurfaceView; super.onCreate(icicle);
import android.view.View; Debug.startMethodTracing("mytrace");
import android.view.Window; Log.e(TAG, "onCreate");
import android.view.WindowManager; getWindow().setFormat(PixelFormat.TRANSLUCENT);
import android.view.View.OnClickListener; requestWindowFeature(Window.FEATURE_NO_TITLE);
import android.view.ViewGroup.LayoutParams; getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
import android.widget.ImageView; WindowManager.LayoutParams.FLAG_FULLSCREEN);

import android.widget.Toast; setContentView(;

PhotoShoot class

First the imports.

Hello World Project
import android.content.Intent; import;

import; import android.content.Intent;

import; import;

import; import;

import; import;

import android.hardware.Camera; import;

import android.os.Bundle; import android.hardware.Camera;

import android.os.Debug; import android.os.Bundle;

import android.provider.MediaStore.Images; import android.os.Debug;

import android.util.Log; import android.provider.MediaStore.Images;

import android.view.SurfaceHolder; import android.util.Log;

import android.view.SurfaceView; import android.view.SurfaceHolder;

import android.view.View; import android.view.SurfaceView;

import android.view.Window; import android.view.View;

import android.view.WindowManager; import android.view.Window;

import android.view.View.OnClickListener; import android.view.WindowManager;

import android.view.ViewGroup.LayoutParams; import android.view.View.OnClickListener;

import android.widget.ImageView; import android.view.ViewGroup.LayoutParams;

import android.widget.Toast; import android.widget.ImageView;
Androids Camera class
Must ask to use the camera in Manifest file
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="" />
<uses-feature android:name="" />
Must ask permission to use Android
Camera or its features
Examples (first one is the one we use)
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="" />
<uses-feature android:name="" />
Android Steps in Using Camera to
take picture (some optional)
1. Obtain an instance of Camera from open(int).
2. Get existing (default) settings with getParameters().
3. If necessary, modify the returned Camera.Parameters object and call setParameters(Camera.Parameters).
4. If desired, call setDisplayOrientation(int).
5. Important: Pass a fully initialized SurfaceHolder to setPreviewDisplay(SurfaceHolder). Without a surface,
the camera will be unable to start the preview.
6. Important: Call startPreview() to start updating the preview surface. Preview must be started before you
can take a picture.
7. When you want, call takePicture(Camera.ShutterCallback, Camera.PictureCallback,
Camera.PictureCallback, Camera.PictureCallback) to capture a photo. Wait for the callbacks to provide
the actual image data.
8. After taking a picture, preview display will have stopped. To take more photos, call startPreview() again
9. Call stopPreview() to stop updating the preview surface.
10. Important: Call release() to release the camera for use by other applications. Applications should release
the camera immediately in onPause() (and re-open() it in onResume()).