Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義照相機倒計時拍照

Android自定義照相機倒計時拍照

編輯:關於Android編程

自定義拍照會用到SurfaceView控件顯示照片的預覽區域,以下是布局文件:

兩個TextView是用來顯示提示信息和倒計時的秒數的

相關教程:Android開發從相機或相冊獲取圖片裁剪

Android啟動相機拍照並返回圖片

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#266194"
 android:orientation="vertical"
 tools:context=".TestActivity" >
 <SurfaceView
 android:id="@+id/surfaceView"
 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="請調整位置到此區域"
 android:textColor="#ff0000"
 android:textSize="32sp" />
 <TextView
 android:id="@+id/tv_time"
 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> 

接下來是mainActivity中的具體實現以及詳細注釋:

package com.dhsr.pujiejia.ui;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import com.example.pujiejiaapp.R;
@SuppressLint({ "NewApi", "SdCardPath" })
public class CameraActivity extends Activity implements Runnable {
 // 預覽圖片范圍
 private SurfaceView surfaceView;
 private TextView tv_time;
 // 倒計時拍攝
 private int cameratime = 4;
 private Camera camera;
 private boolean preview = false;
 // 文件名字
 private String filename;
 // 文件名字的帶的時間戳
 private String timeString;
 // 格式化時間
 private SimpleDateFormat dateFormat;
 // 日期對象
 private Date date;
 // 控制線程
 boolean stopThread = false;
 private File file;
 String photo;
 private Handler mHandler = new Handler() {
 public void handleMessage(android.os.Message msg) {
 int what = msg.what;
 switch (what) {
 case 222:
 tv_time.setText("" + cameratime);
 if ("0".equals(tv_time.getText().toString())) {
  tv_time.setText("拍攝成功!");
  takePhoto();
 }
 break;
 }
 };
 };
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 // TODO Auto-generated method stub
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_test);
 CameraActivity.this.setFinishOnTouchOutside(false);
 // 初始化數據
 findView();
 surfaceView.getHolder().addCallback(new SufaceListener());
 /* 下面設置Surface不維護自己的緩沖區,而是等待屏幕的渲染引擎將內容推送到用戶面前 */
 surfaceView.getHolder()
 .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 surfaceView.getHolder().setFixedSize(200, 200); // 設置分辨率
 }
 @Override
 protected void onStart() {
 // TODO Auto-generated method stub
 super.onStart();
 // 開啟線程
 new Thread(this).start();
 }
 private final class SufaceListener implements SurfaceHolder.Callback {
 /**
 * surface改變
 */
 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width,
 int height) {
 }
 /**
 * surface創建
 */
 @Override
 public void surfaceCreated(SurfaceHolder holder) {
 try {
 for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
  CameraInfo info = new CameraInfo();
  Camera.getCameraInfo(i, info);
  // 調用系統的前置攝像頭
  if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
  camera = Camera.open(i);
  }
 }
 Camera.Parameters parameters = camera.getParameters();
 /* 每秒從攝像頭捕獲5幀畫面, */
 parameters.setPreviewFrameRate(5);
 /* 設置照片的輸出格式:jpg */
 parameters.setPictureFormat(PixelFormat.JPEG);
 /* 照片質量 */
 parameters.set("jpeg-quality", 85);
 WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
 camera.setParameters(parameters);
 camera.setPreviewDisplay(surfaceView.getHolder());// 通過SurfaceView顯示取景畫面
 camera.startPreview();
 preview = true;
 } catch (Exception e) {
 }
 }
 /**
 * surface銷毀
 */
 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
 if (camera != null) {
 if (preview)
  camera.stopPreview();
 camera.release();
 camera = null;
 }
 }
 }
 /**
 * 拍攝照片
 */
 private void takePhoto() {
 // 執行拍照效果
 camera.takePicture(null, null, new Camera.PictureCallback() {
 @Override
 public void onPictureTaken(byte[] data, Camera camera) {
 try {
  Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
  data.length);
  timeString = formatDate();
  //保存到data/data目錄自定義文件夾下
  filename = "/data/data/com.example.pujiejiaapp/images/"
  + timeString + ".jpg";
  File file = new File(filename);
  boolean createNewFile = file.createNewFile()
  System.out.println("創建文件夾成功沒有" + createNewFile);
  System.out.println(file);
  FileOutputStream outStream = new FileOutputStream(file);
  bitmap.compress(Bitmap.CompressFormat.JPEG, 60, outStream);
  outStream.flush();
  outStream.close();
  // 重新浏覽
  camera.stopPreview();
  camera.startPreview();
  preview = true;
 } catch (Exception e) {
  e.printStackTrace();
 } finally {
 }
 }
 });
 }
 @Override
 public void run() {
 while (!stopThread) {
 try {
 //按秒數倒計時
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 cameratime--;
 mHandler.sendEmptyMessage(222);
 if (cameratime <= 0) {
 break;
 }
 }
 }
 // 初始化數據
 private void findView() {
 surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView);
 tv_time = (TextView) findViewById(R.id.tv_time);
 }
 // 格式化系統的時間
 public String formatDate() {
 date = new Date(System.currentTimeMillis());
 // 日期格式
 dateFormat = new SimpleDateFormat("'IMG'_yyyyMMddHHmmss");
 return dateFormat.format(date);
 }
 @Override
 protected void onDestroy() {
 // TODO Auto-generated method stub
 // 線程已關閉
 super.onDestroy();
 stopThread = true;
 }
} 

核心代碼詳解:

1.創建SurfaceView時,surfaceCreated()方法中

for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
  CameraInfo info = new CameraInfo();
  Camera.getCameraInfo(i, info);
  // 調用系統的前置攝像頭
  if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
  camera = Camera.open(i);
  }
 }

此部分代碼為打開相機時默認打開前置攝像頭CameraInfo.CAMERA_FACING_BACK為默認打開後置攝像頭,CameraInfo.CAMERA_FACING_FRONT前置攝像頭

2.照片拍攝takePhoto()方法中:

Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
  data.length);
  timeString = formatDate();
  filename = "/data/data/com.example.pujiejiaapp/images/"
  + timeString + ".jpg";
  photo = timeString + ".jpg";
  File file = new File(filename);
  boolean createNewFile = file.createNewFile();
  FileOutputStream outStream = new FileOutputStream(file);
  bitmap.compress(Bitmap.CompressFormat.JPEG, 60, outStream);

此部分代碼為將拍攝到的圖片保存為以bitmap格式保存在指定的目錄下

3.開子線程用於倒計時拍攝

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

希望大家理解核心代碼的詳細注釋,歡迎提供意見,希望能給大家帶來幫助,謝謝!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved