Building a Timer Based Camera

Write App Reviews

Build your own Android App Dev Empire

Get Instant Access

To rectify the situation just described, we can add a time delay to the taking of the picture. Let's update our SnapShot example so that picture is taken ten seconds after pushing a button.

In order to accomplish this, we'll need to use something like a java.util.Timer. Unfortunately, in Android, using a Timer creates some complications as it introduces a separate thread. To have separate threads interact with the UI, we need to use a Handler to cause an action to occur on the main thread.

The other use of a Handler is to schedule something to happen in the future. This capability of a Handler makes using the Timer unnecessary.

To create a Handler that will execute something in the future, we simply construct a generic one:

Handler timerHandler = new Handler();

We then have to create a Runnable. This Runnable will contain within its run method the action to happen later. In our case, we want this action to occur ten seconds later and trigger the taking of the picture:

Runnable timerTask = new Runnable() { public void run() {

camera.takePicture(null,null,null,TimerSnapShot.this);

That should cover it. Now when we push a button, we simply need to schedule it:

timerHandler.postDelayed(timerTask, 10000);

This tells the timerHandler to call our timerTask method 10 seconds (10000 milliseconds) in the future.

In the following example, we are creating a Handler and having it call a method every second. In this way, we can provide a countdown on the screen to the user.

package com.apress.proandroidmedia.ch2.timersnapshot;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.OutputStream;

import java.util.Iterator;

import java.util.List;

import android.app.Activity;

import android.content.ContentValues;

import android.content.res.Configuration;

import android.hardware.Camera;

import android.net.Uri;

import android.os.Bundle;

import android.os.Handler;

import android.provider.MediaStore.Images.Media;

import android.util.Log;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;

import android.widget.Toast;

public class TimerSnapShot extends Activity implements OnClickListener,^ SurfaceHolder.Callback, Camera.PictureCallback {

SurfaceView cameraView; SurfaceHolder surfaceHolder; Camera camera;

This activity is very similar to our SnapShot activity. We are going to add a Button to trigger the start of countdown and a TextView to display the countdown.

Button startButton; TextView countdownTextView;

We'll also need a Handler, in this case timerUpdateHandler, a Boolean to help us keep track of whether the timer has started (timerRunning), and we'll have an integer (currentTime) that will keep track of the countdown.

Handler timerUpdateHandler; boolean timerRunning = false; int currentTime = 10;

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);

cameraView = (SurfaceView) this.findViewById(R.id.CameraView); surfaceHolder = cameraView.getHolder();

surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceHolder.addCallback(this);

Next, we'll obtain references to the new UI elements (defined in the layout XML) and make our activity be the OnClickListener for the Button. We can do this because our activity implements OnClickListener.

countdownTextView = (TextView) findViewById(R.id.CountDownTextView); startButton = (Button) findViewById(R.id.CountDownButton); startButton.setOnClickListener(this);

The last thing we'll do in our onCreate method is instantiate our Handler object. timerUpdateHandler = new Handler();

Our onClick method will be called when the startButton Button is pressed. We'll make sure the timer routine isn't already running by checking our timerRunning Boolean, and if it isn't, we'll call timerUpdateTask Runnable (described here) without delay through our Handler object, timerUpdateHandler.

public void onClick(View v) {

if (!timerRunning) {

timerRunning = true;

timerUpdateHandler.post(timerUpdateTask);

Here is our Runnable called timerUpdateTask. This is the object that contains the run method that will be triggered by our timerUpdateHandler object.

private Runnable timerUpdateTask = new Runnable() {

If the currentTime, the integer holding our countdown, is greater than 1, we'll decrement it and schedule the Handler call again in 1 second.

currentTime-- ;

timerUpdateHandler.postDelayed(timerUpdateTask, 1000);

If currentTime isn't greater than 1, we'll actually trigger the camera to take the picture and reset all of our tracking variables.

camera.takePicture(null,null ,TimerSnapShot.this); timerRunning = false;

currentTime = 10;

No matter what, we'll update the TextView to display the current time remaining before the picture is taken.

countdownTextView.setText(""+currentTime);

The rest of the activity is essentially the same as the foregoing SnapShot example.

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { camera.startPreview();

public void surfaceCreated(SurfaceHolder holder) { camera = Camera.open(); try {

camera.setPreviewDisplay(holder);

Camera.Parameters parameters = camera.getParameters(); if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)

parameters.set("orientation", "portrait");

// For Android Version 2.2 and above camera.setDisplayOrientation(90);

// For Android Version 2.0 and above parameters.setRotation(90);

camera.setParameters(parameters);

catch (IOException exception) {

camera.release();

public void surfaceDestroyed(SurfaceHolder holder) { camera.stopPreview(); camera.release();

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

getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues()); try {

OutputStream imageFileOS =

getContentResolver().openOutputStream(imageFileUri); imageFileOS.write(data); imageFileOS.flush(); imageFileOS.close();

Toast t = Toast.makeText(this,"Saved JPEG!", Toast.LENGTH_SHORT); t.show();

} catch (FileNotFoundException e) {

Toast t = Toast.makeText(this,e.getMessage(), Toast.LENGTH_SHORT); t.show(); } catch (IOException e) {

Toast t = Toast.makeText(this,e.getMessage(), Toast.LENGTH_SHORT); t.show();

camera.startPreview();

The layout XML is a bit different. In this application, we are displaying the Camera preview SurfaceView within a FrameLayout along with a LinearLayout that contains the TextView for displaying the countdown and the Button for triggering the countdown. The FrameLayout aligns all of its children to the top left and on top of each other. This way the TextView and Button appear over top of the Camera preview.

<?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" >

<FrameLayout android:id="@+id/FrameLayout01" android:layout_width="wrap_content"^ android:layout_height="wrap_content">

<SurfaceView android:id="@+id/CameraView" android:layout_width="fill_parent"^ android:layout_height="fill_parent"></SurfaceView> <LinearLayout android:id="@+id/LinearLayout01" android:layout_width="wrap_content"^ android:layout_height="wrap_content">

<TextView android:id="@+id/CountDownTextView" android:text="10"^ android:textSize="100dip" android:layout_width="fill_parent"^ android:layout_height="wrap_content"^

android:layout_gravity="center_vertical|center_horizontal|center"></TextView> <Button android:layout_width="wrap_content" android:layout_height="wrap_content"^

android:id="@+id/CountDownButton" android:text="Start Timer"></Button> </LinearLayout> </FrameLayout> </LinearLayout>

Last, we need to make sure our AndroidManifest.xml file contains the CAMERA permission.

<uses-permission android:name="android.permission.CAMERA"></uses-permission>

[√úC9HA raffle 4:41PM

Timer Snapshot

Figure 2-5. Camera with countdown timer

Was this article helpful?

+1 0

Post a comment