2015/11/03

Android Camera 實現連拍功能

實現連拍的思維有兩種,一個是透過Focus(對焦),而另一個則不透過Focus(對焦)來連續拍照

首先Focus思維是當照片擷取完後恢復到預覽畫面還在對焦時透過onAutoFocus的參數success成立時再度呼叫takePicture

而另一種則是透過takePicture進行第一次拍照,完成後開啟預覽畫面時再度呼叫takePicture本身
兩者直到temp_count條件成立才不持續拍攝,但是用Focus對焦本身比較容易失敗啊!!!
另外並不是每隻手機都支援對焦功能,所以開發者也要去確認手機是否支援對焦功能
可能是小弟我手機爛到不行,有沒有好心人要贊助啊XD

Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cyfang.test"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="15" />

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

    <uses-feature android:name="android.hardware.camera.autofocus" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>




透過Foucs:
package com.cyfang.test;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.List;

import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
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.Toast;

public class MainActivity extends Activity implements SurfaceHolder.Callback, PictureCallback {

 /** SurfaceView */
 private SurfaceView surfaceView;

 /** Holder */
 private SurfaceHolder holder;

 /** 相機 */
 private Camera camera;

 /** 拍照按鈕 */
 private Button buttonTake;

 /** 照片寬度 */
 private int picWidth;

 /** 照片寬度 */
 private int picHeight;

 /** 預覽寬度 */
 private int pvWidth;

 /** 預覽高度 */
 private int pvHeight;

 /** 連拍次數 */
 private int take_count = 3;

 /** 連拍次數 */
 private int temp_count = take_count;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  buttonTake = (Button) findViewById(R.id.button1);

  // 按鈕點擊事件
  buttonTake.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    camera.takePicture(null, null, MainActivity.this);
   }
  });

  surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
  surfaceView.setZOrderOnTop(false);
  holder = surfaceView.getHolder();
  holder.addCallback(this);
  holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 }

 @Override
 protected void onStop() {
  if (camera != null) {
   camera.stopPreview();
   camera.release();
   camera = null;
  }
  super.onStop();
 }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  // TODO Auto-generated method stub

 }

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
  try {
   if (camera == null) {
    camera = Camera.open(CameraInfo.CAMERA_FACING_BACK);

    // 取得相機參數
    Parameters parameters = camera.getParameters();

    // 判斷能不能對焦
    if (parameters.getSupportedFocusModes().contains(Parameters.FOCUS_MODE_AUTO)) {
     parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
     if (parameters.getSupportedFocusModes().contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
      parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
     else
      Toast.makeText(MainActivity.this, "抱歉您的手機不支援對焦連拍", 1).show();
    }

    // 關閉閃光燈
    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);

    // 預覽尺寸清單
    List<Size> previewList = parameters.getSupportedPreviewSizes();

    // 照片尺寸清單
    List<Size> pictureList = parameters.getSupportedPictureSizes();

    picWidth = pictureList.get(0).width;
    picHeight = pictureList.get(0).height;
    // 設定最佳照片尺寸
    parameters.setPictureSize(picWidth, picHeight);

    pvWidth = previewList.get(0).width;
    pvHeight = previewList.get(0).height;

    // 設定最佳預覽尺寸
    parameters.setPreviewSize(pvWidth, pvHeight);

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
     camera.setDisplayOrientation(90);
     parameters.setRotation(90);
    }

    // 設定相機參數
    camera.setParameters(parameters);

    // 設定顯示的Holder
    camera.setPreviewDisplay(holder);

    // 開始顯示
    camera.startPreview();
   }
  } catch (IOException e) {
  } catch (RuntimeException e) {
  }

 }

 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
  // TODO Auto-generated method stub

 }

 @Override
 public void onPictureTaken(byte[] data, Camera camera) {
  try {
   Log.i("Count", temp_count + "");

   ByteArrayInputStream stream = new ByteArrayInputStream(data);
   Bitmap bitmap = BitmapFactory.decodeStream(stream);
   stream.close();
   stream = null;

   FileOutputStream fileOutputStream = new FileOutputStream(
     new File("/sdcard/" + new Date().getTime() + ".jpg"));
   bitmap.compress(CompressFormat.JPEG, 90, fileOutputStream);
   bitmap = null;

   // 寫入檔案
   fileOutputStream.flush();
   fileOutputStream.close();
   fileOutputStream = null;
   camera.startPreview();

   if (temp_count-- != 1) {
    camera.cancelAutoFocus();
    camera.autoFocus(autoFocusCallback);
   } else {
    camera.cancelAutoFocus();
    temp_count = take_count;
   }

  } catch (IOException e) {
   Log.i("Tack_IOException", e.getMessage());
  }
 }

 private final AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {

  @Override
  public void onAutoFocus(boolean success, Camera camera) {
   if (success)
    camera.takePicture(null, null, MainActivity.this);
  }
 };
}

不透過Focus:
package com.cyfang.test;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.List;

import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
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;

public class MainActivity extends Activity implements SurfaceHolder.Callback, PictureCallback {

 /** SurfaceView */
 private SurfaceView surfaceView;

 /** Holder */
 private SurfaceHolder holder;

 /** 相機 */
 private Camera camera;

 /** 拍照按鈕 */
 private Button buttonTake;

 /** 照片寬度 */
 private int picWidth;

 /** 照片寬度 */
 private int picHeight;

 /** 預覽寬度 */
 private int pvWidth;

 /** 預覽高度 */
 private int pvHeight;

 /** 連拍次數 */
 private int take_count = 3;

 /** 連拍次數 */
 private int temp_count = take_count;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  buttonTake = (Button) findViewById(R.id.button1);

  // 按鈕點擊事件
  buttonTake.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    camera.takePicture(null, null, MainActivity.this);
   }
  });

  surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
  surfaceView.setZOrderOnTop(false);
  holder = surfaceView.getHolder();
  holder.addCallback(this);
  holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 }

 @Override
 protected void onStop() {
  if (camera != null) {
   camera.stopPreview();
   camera.release();
   camera = null;
  }
  super.onStop();
 }

 @Override
 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  // TODO Auto-generated method stub

 }

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
  try {
   if (camera == null) {
    camera = Camera.open(CameraInfo.CAMERA_FACING_BACK);

    // 取得相機參數
    Parameters parameters = camera.getParameters();

    // 關閉閃光燈
    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);

    // 預覽尺寸清單
    List<size> previewList = parameters.getSupportedPreviewSizes();

    // 照片尺寸清單
    List<size> pictureList = parameters.getSupportedPictureSizes();

    picWidth = pictureList.get(0).width;
    picHeight = pictureList.get(0).height;
    // 設定最佳照片尺寸
    parameters.setPictureSize(picWidth, picHeight);

    pvWidth = previewList.get(0).width;
    pvHeight = previewList.get(0).height;

    // 設定最佳預覽尺寸
    parameters.setPreviewSize(pvWidth, pvHeight);

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
     camera.setDisplayOrientation(90);
     parameters.setRotation(90);
    }

    // 設定相機參數
    camera.setParameters(parameters);

    // 設定顯示的Holder
    camera.setPreviewDisplay(holder);

    // 開始顯示
    camera.startPreview();
   }
  } catch (IOException e) {
  } catch (RuntimeException e) {
  }

 }

 @Override
 public void surfaceDestroyed(SurfaceHolder holder) {
  // TODO Auto-generated method stub

 }

 @Override
 public void onPictureTaken(byte[] data, Camera camera) {
  try {
   Log.i("Count", temp_count + "");

   ByteArrayInputStream stream = new ByteArrayInputStream(data);
   Bitmap bitmap = BitmapFactory.decodeStream(stream);
   stream.close();
   stream = null;

   FileOutputStream fileOutputStream = new FileOutputStream(
     new File("/sdcard/" + new Date().getTime() + ".jpg"));
   bitmap.compress(CompressFormat.JPEG, 90, fileOutputStream);
   bitmap = null;

   // 寫入檔案
   fileOutputStream.flush();
   fileOutputStream.close();
   fileOutputStream = null;
   camera.startPreview();

   if (temp_count-- != 1)
    camera.takePicture(null, null, this);
   else
    temp_count = take_count;

  } catch (IOException e) {
   Log.i("Tack_IOException", e.getMessage());
  }
 }

}

執行結果: