SoFunction
Updated on 2025-03-11

Android custom camera countdown to take photos

Customized photo shooting will use the SurfaceView control to display the preview area of ​​the photo. The following is the layout file:

Two TextViews are used to display prompt information and countdown seconds.

Related tutorials:Android development gets cropped image from camera or album

Android starts the camera to take pictures and return to pictures

<RelativeLayout xmlns:andro
 xmlns:tools="/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#266194"
 android:orientation="vertical"
 tools:context=".TestActivity" >
 <SurfaceView
 android:
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_centerInParent="true" />
 <LinearLayout
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_centerInParent="true"
 android:orientation="vertical" >
 <TextView
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Please adjust the position to this area"
 android:textColor="#ff0000"
 android:textSize="32sp" />
 <TextView
 android:
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:paddingTop="10dp"
 android:gravity="center_horizontal"
 android:textColor="#266194"
 android:textSize="32sp" />
 </LinearLayout>
</RelativeLayout> 

Next is the specific implementation and detailed comments in mainActivity:

package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
@SuppressLint({ "NewApi", "SdCardPath" })
public class CameraActivity extends Activity implements Runnable {
 // Preview the picture range private SurfaceView surfaceView;
 private TextView tv_time;
 // Countdown shooting private int cameratime = 4;
 private Camera camera;
 private boolean preview = false;
 // File name private String filename;
 // Timestamp with file name private String timeString;
 // Format time private SimpleDateFormat dateFormat;
 // Date object private Date date;
 // Control thread boolean stopThread = false;
 private File file;
 String photo;
 private Handler mHandler = new Handler() {
 public void handleMessage( msg) {
 int what = ;
 switch (what) {
 case 222:
 tv_time.setText("" + cameratime);
 if ("0".equals(tv_time.getText().toString())) {
  tv_time.setText("The shooting was successful!");
  takePhoto();
 }
 break;
 }
 };
 };
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 // TODO Auto-generated method stub
 (savedInstanceState);
 setContentView(.activity_test);
 (false);
 // Initialize the data findView();
 ().addCallback(new SufaceListener());
 /* Setting the Surface below does not maintain its own buffer, but waits for the rendering engine of the screen to push the content to the user */
 ()
 .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 ().setFixedSize(200, 200); // Set resolution }
 @Override
 protected void onStart() {
 // TODO Auto-generated method stub
 ();
 // Turn on thread new Thread(this).start();
 }
 private final class SufaceListener implements  {
 /**
  * surface change
  */
 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width,
 int height) {
 }
 /**
  * surface creation
  */
 @Override
 public void surfaceCreated(SurfaceHolder holder) {
 try {
 for (int i = 0; i < (); i++) {
  CameraInfo info = new CameraInfo();
  (i, info);
  // Call the front camera of the system  if ( == CameraInfo.CAMERA_FACING_FRONT) {
  camera = (i);
  }
 }
  parameters = ();
 /* Capture 5 frames of the camera per second, */
 (5);
 /* Set the output format of the photo: jpg */
 ();
 /* Photo quality */
 ("jpeg-quality", 85);
 WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
 (parameters);
 (());// Display the framing screen through SurfaceView ();
 preview = true;
 } catch (Exception e) {
 }
 }
 /**
  * surface destruction
  */
 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
 if (camera != null) {
 if (preview)
  ();
 ();
 camera = null;
 }
 }
 }
 /**
  * Take photos
  */
 private void takePhoto() {
 // Perform photo effects (null, null, new () {
 @Override
 public void onPictureTaken(byte[] data, Camera camera) {
 try {
  Bitmap bitmap = (data, 0,
  );
  timeString = formatDate();
  //Save to the data/data directory custom folder  filename = "/data/data//images/"
  + timeString + ".jpg";
  File file = new File(filename);
  boolean createNewFile = ()
  ("Folder creation was successful" + createNewFile);
  (file);
  FileOutputStream outStream = new FileOutputStream(file);
  (, 60, outStream);
  ();
  ();
  // Rebrowse  ();
  ();
  preview = true;
 } catch (Exception e) {
  ();
 } finally {
 }
 }
 });
 }
 @Override
 public void run() {
 while (!stopThread) {
 try {
 //Count down by seconds (1000);
 } catch (InterruptedException e) {
 // TODO Auto-generated catch block
 ();
 }
 cameratime--;
 (222);
 if (cameratime <= 0) {
 break;
 }
 }
 }
 // Initialize the data private void findView() {
 surfaceView = (SurfaceView) ();
 tv_time = (TextView) findViewById(.tv_time);
 }
 // Time to format the system public String formatDate() {
 date = new Date(());
 // Date format dateFormat = new SimpleDateFormat("'IMG'_yyyyMMddHHmmss");
 return (date);
 }
 @Override
 protected void onDestroy() {
 // TODO Auto-generated method stub
 // The thread has been closed ();
 stopThread = true;
 }
} 

Detailed explanation of the core code:

1. When creating a SurfaceView, the surfaceCreated() method is in the surfaceCreated() method.

for (int i = 0; i < (); i++) {
  CameraInfo info = new CameraInfo();
  (i, info);
  // Call the front camera of the system  if ( == CameraInfo.CAMERA_FACING_FRONT) {
  camera = (i);
  }
 }

This part of the code is to turn on the front camera by default when opening the camera CameraInfo.CAMERA_FACING_BACK is to turn on the rear camera by default, CameraInfo.CAMERA_FACING_FRONT front camera is to turn on the rear camera by default.

2. Photo shooting takesPhoto() method:

Bitmap bitmap = (data, 0,
  );
  timeString = formatDate();
  filename = "/data/data//images/"
  + timeString + ".jpg";
  photo = timeString + ".jpg";
  File file = new File(filename);
  boolean createNewFile = ();
  FileOutputStream outStream = new FileOutputStream(file);
  (, 60, outStream);

This part of the code saves the captured images as bitmap format and saves them in the specified directory

3. Opening the child thread is used for countdown shooting

public void run() {
 while (!stopThread) {
 try {
 (1000);
 } catch (InterruptedException e) {
 // TODO Auto-generated catch block
 ();
 }
 cameratime--;
 (222);
 if (cameratime <= 0) {
 break;
 }
 }
 }

I hope everyone understands the detailed comments of the core code. I welcome the advice. I hope it can help you. Thank you!