天天看點

Android Camera2使用

1. 相機使用流程

Android Camera2使用

圖1.jpg

2. SurfaceView

/**
 * Android 5.0 使用Camera2 照相
 * 使用SurfaceView顯示
 * 主要步驟:
 * 1. 獲得攝像頭管理器CameraManager mCameraManager,mCameraManager.openCamera()來打開攝像頭
 * 2. 指定要打開的攝像頭,并建立openCamera()所需要的CameraDevice.StateCallback stateCallback
 * 3. 在CameraDevice.StateCallback stateCallback中調用takePreview(),這個方法中,使用CaptureRequest.Builder建立預覽需要的CameraRequest,并初始化了CameraCaptureSession,最後調用了setRepeatingRequest(previewRequest, null, childHandler)進行了預覽
 * 4. 點選拍照按鈕,調用takePicture(),這個方法内,最終調用了capture(mCaptureRequest, null, childHandler)
 * 5. 在new ImageReader.OnImageAvailableListener(){}回調方法中,将拍照拿到的圖檔進行展示
 */
public class CameraSurfaceFragment extends Fragment {
  /**照相機裝置請求碼*/
  private static final int REQUEST_CAMERA_CODE = 0x100;
  /**拍照*/
  private Button mBtnTake;
  /**顯示拍照好的圖檔*/
  private ImageView mIvShow;
  /**預覽視窗*/
  private SurfaceView mSurfaceView;
  /**預覽視窗Holder*/
  private SurfaceHolder mSurfaceHolder;
  /**子線程Handler*/
  private Handler mChildHandler;
  /**主線程Handler*/
  private Handler mMainHandler;
  /**照相機ID,辨別前置,後置*/
  private String mCameraId;
  /**圖檔讀取器*/
  private ImageReader mImageReader;
  /**攝像頭管理者*/
  private CameraManager mCameraManager;
  /**照相機裝置*/
  private CameraDevice mCameraDevice;
  /**照相會話*/
  private CameraCaptureSession mCameraCaptureSession;
  /**方向清單*/
  private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
  
  /**
   * 攝像頭狀态監聽
   */
  private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice camera) {
      // 打開攝像頭
      mCameraDevice = camera;
      // 開啟預覽
      takePreview();
    }
  
    @Override
    public void onDisconnected(@NonNull CameraDevice camera) {
      // 關閉攝像頭
      if (null != mCameraDevice) {
        // 關閉攝像頭
        mCameraDevice.close();
        mCameraDevice = null;
      }
    }
  
    @Override
    public void onError(@NonNull CameraDevice camera, int error) {
      // 攝像頭異常
      Toast.makeText(getContext(), "攝像頭開啟失敗", Toast.LENGTH_SHORT).show();
    }
  };
  
  static {
    ORIENTATIONS.append(Surface.ROTATION_0, 90);
    ORIENTATIONS.append(Surface.ROTATION_90, 0);
    ORIENTATIONS.append(Surface.ROTATION_180, 270);
    ORIENTATIONS.append(Surface.ROTATION_270, 180);
  }
  
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                           Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment_camera_surface, container, false);
    initView(root);
    initListener();
    return root;
  }
  
  /**
   * 初始化View
   */
  private void initView(View view) {
    // 綁定View
    mIvShow = view.findViewById(R.id.iv_show);
    mBtnTake = view.findViewById(R.id.btn_take);
    mSurfaceView = view.findViewById(R.id.sv_camera);
    // 擷取Holder
    mSurfaceHolder = mSurfaceView.getHolder();
    // 設定螢幕常量
    mSurfaceHolder.setKeepScreenOn(true);
    // 設定SurfaceView回調
    mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
      @Override
      public void surfaceCreated(SurfaceHolder holder) {
        // SurfaceView 建立
        initCamera();
      }
  
      @Override
      public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // SurfaceView 改變
      }
  
      @Override
      public void surfaceDestroyed(SurfaceHolder holder) {
        // SurfaceView 銷毀
        // 銷毀照相機裝置
        if (null != mCameraDevice) {
          mCameraDevice.close();
          mCameraDevice = null;
        }
      }
    });
  }
  
  /**
   * 初始化監聽器
   */
  private void initListener() {
    mBtnTake.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        takePicture();
      }
      
    });
  }
  
  /**
   * 初始化照相機
   */
  private void initCamera() {
    // 建立Handler線程并啟動
    HandlerThread handlerThread = new HandlerThread("Camera");
    handlerThread.start();
    // 建立子線程Handler
    mChildHandler = new Handler(handlerThread.getLooper());
    // 建立主線程Handler
    mMainHandler = new Handler(Looper.getMainLooper());
    // 設定後置攝像頭ID
    mCameraId = String.valueOf(CameraCharacteristics.LENS_FACING_FRONT);
    // 建立圖檔讀取器
    mImageReader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG, 1);
    // 圖檔讀取器設定圖檔可用監聽
    mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
      @Override
      public void onImageAvailable(ImageReader reader) {
        showImage(reader);
      }
    }, mMainHandler);
    // 擷取攝像頭管理
    mCameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
    // 打開攝像頭
    try {
      if (ActivityCompat.checkSelfPermission
              (getContext(), Manifest.permission.CAMERA)
              != PackageManager.PERMISSION_GRANTED) {
        // 申請權限
        requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_CODE);
      } else {
        // 打開攝像頭
        mCameraManager.openCamera(mCameraId, mStateCallback, mMainHandler);
      }
    } catch (CameraAccessException e) {
      e.printStackTrace();
    }
  }
  
  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (REQUEST_CAMERA_CODE == requestCode) {
      // 權限允許
      if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        try {
          if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            return;
          }
          mCameraManager.openCamera(mCameraId, mStateCallback, mMainHandler);
        } catch (CameraAccessException e) {
          e.printStackTrace();
        }
      } else {
        // 權限拒絕
        Toast.makeText(getContext(), "無權限", Toast.LENGTH_SHORT).show();
      }
    }
  }
  
  /**
   * 圖檔可用後,讀取并顯示圖檔
   * @param reader 圖檔讀取器
   */
  private void showImage(ImageReader reader) {
    // 拿到圖檔資料
    Image image = reader.acquireNextImage();
    // 擷取位元組緩沖
    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
    // 建立與緩沖區相同的位元組數組
    byte[] bytes = new byte[buffer.remaining()];
    // 将資料讀取位元組數組
    buffer.get(bytes);
    // 建立圖檔
    final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
    // 顯示圖檔
    if (null != bitmap) {
      mIvShow.setImageBitmap(bitmap);
    }
  }
  
  /**
   * 預覽
   */
  private void takePreview() {
    try {
      // 建立預覽需要的CaptureRequest.Builder
      final CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
      // 将SurfaceView的surface作為Builder的目标
      builder.addTarget(mSurfaceHolder.getSurface());
      // 建立CameraCaptureSession,該對象負責管理處理預覽請求和拍照請求
      mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
          // 檢測裝置是否為空
          if (null == mCameraDevice) return;
          // 配置
          // 當攝像頭已經準備好時,開始顯示預覽
          mCameraCaptureSession = session;
          try {
            // 自動對焦
            builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            // 打開閃光燈
            builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            // 顯示預覽
            CaptureRequest request = builder.build();
            // 會話設定重複請求
            mCameraCaptureSession.setRepeatingRequest(request, null, mChildHandler);
          } catch (CameraAccessException e) {
            e.printStackTrace();
          }
        }
  
        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
          Toast.makeText(getContext(), "配置失敗", Toast.LENGTH_SHORT).show();
        }
      }, mChildHandler);
    } catch (CameraAccessException e) {
      e.printStackTrace();
    }
  }
  
  /**
   * 拍照
   */
  private void takePicture() {
    // 判斷裝置是否為空
    if (null == mCameraDevice) return;
    // 建立拍照需要的CaptureRequest.Builder
    final CaptureRequest.Builder builder;
    try {
      // 建立拍照請求
      builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
      // 将imageReader的surface作為CaptureRequest.Builder的木白哦
      builder.addTarget(mImageReader.getSurface());
      // 自動對焦
      builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
      // 自動曝光
      builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
      // 擷取手機方向
      int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
      // 根據裝置方向計算設定照片的方向
      builder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
      // 拍照
      CaptureRequest request = builder.build();
      // 拍照會話執行拍照
      mCameraCaptureSession.capture(request, null, mChildHandler);
    } catch (CameraAccessException e) {
      e.printStackTrace();
    }
  }
}
           

3. TextureView

/**
 * Camera2 與 Texture使用
 */
public class CameraTextureFragment extends Fragment {
  /**相機權限請求辨別*/
  private static final int REQUEST_CAMERA_CODE = 0x100;
  /**預覽*/
  private TextureView mTextureView;
  /**拍照按鈕*/
  private Button mBtnTake;
  /**圖檔*/
  private ImageView mImageView;
  /**照相機ID,辨別前置後置*/
  private String mCameraId;
  /**相機尺寸*/
  private Size mCaptureSize;
  /**圖像讀取者*/
  private ImageReader mImageReader;
  /**圖像主線程Handler*/
  private Handler mCameraHandler;
  /**相機裝置*/
  private CameraDevice mCameraDevice;
  /**預覽大小*/
  private Size mPreviewSize;
  /**相機請求*/
  private CaptureRequest.Builder mCameraCaptureBuilder;
  /**相機拍照捕獲會話*/
  private CameraCaptureSession mCameraCaptureSession;
  /**相機管理者*/
  private CameraManager mCameraManager;
  /**相機裝置狀态回調*/
  private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice camera) {
      // 打開
      mCameraDevice = camera;
      // 開始預覽
      takePreview();
    }
  
    @Override
    public void onDisconnected(@NonNull CameraDevice camera) {
      // 斷開連接配接
      camera.close();
      mCameraDevice = null;
    }
  
    @Override
    public void onError(@NonNull CameraDevice camera, int error) {
      // 異常
      camera.close();
      mCameraDevice = null;
    }
  };
  
  
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                           Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.fragment_camera_texture, container, false);
    initView(root);
    initListener();
    return root;
  }
  
  /**
   * 初始化View
   */
  private void initView(View view) {
    // 初始化View
    mImageView = view.findViewById(R.id.iv_show);
    mTextureView = view.findViewById(R.id.tv_camera);
    mBtnTake = view.findViewById(R.id.btn_take);
  }
  
  @Override
  public void onResume() {
    super.onResume();
    mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
      @Override
      public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        // SurfaceTexture可用
        // 設定相機參數并打開相機
        setUpCamera(width, height);
        openCamera();
      }
  
      @Override
      public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        // SurfaceTexture大小改變
      }
  
      @Override
      public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        // SurfaceTexture 銷毀
        return false;
      }
  
      @Override
      public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        // SurfaceTexture 更新
      }
    });
  }
  
  /**
   * 打開相機
   */
  private void openCamera() {
    // 擷取照相機管理者
    mCameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
    try {
      if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_CODE);
        return;
      }
      // 打開相機
      mCameraManager.openCamera(mCameraId, mStateCallback, mCameraHandler);
    } catch (CameraAccessException e) {
      e.printStackTrace();
    }
  }
  
  @Override
  public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (REQUEST_CAMERA_CODE == requestCode) {
      // 權限允許
      if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        try {
          if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            return;
          }
          mCameraManager.openCamera(mCameraId, mStateCallback, mCameraHandler);
        } catch (CameraAccessException e) {
          e.printStackTrace();
        }
      } else {
        // 權限拒絕
        Toast.makeText(getContext(), "無權限", Toast.LENGTH_SHORT).show();
      }
    }
  }
  
  /**
   * 設定相機參數
   * @param width 寬度
   * @param height 高度
   */
  private void setUpCamera(int width, int height) {
    // 建立Handler
    mCameraHandler = new Handler(Looper.getMainLooper());
    // 擷取攝像頭的管理者
    CameraManager cameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
    try {
      // 周遊所有攝像頭
      for (String cameraId : cameraManager.getCameraIdList()) {
        // 相機特性
        CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraId);
        // 擷取攝像頭是前置還是後置
        Integer facing = cameraCharacteristics.get(CameraCharacteristics.LENS_FACING);
        // 此處預設打開後置攝像頭
        if (null != facing && CameraCharacteristics.LENS_FACING_FRONT == facing)  continue;
        // 擷取StreamConfigurationMap,管理攝像頭支援的所有輸出格式和尺寸
        StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        assert map != null;
        // 根據TextureView的尺寸設定預覽尺寸
        mPreviewSize = getOptimalSize(map.getOutputSizes(SurfaceTexture.class), width, height);
        // 擷取相機支援的最大拍照尺寸
        mCaptureSize = Collections.max(
                Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new Comparator<Size>() {
                  @Override
                  public int compare(Size lhs, Size rhs) {
                    return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getHeight() * rhs.getWidth());
                  }
                });
        // 此處ImageReader用于拍照所需
        setupImageReader();
        // 為攝像頭指派
        mCameraId = cameraId;
        break;
      }
    } catch (CameraAccessException e) {
      e.printStackTrace();
    }
  }
  
  /**
   * 設定ImageReader
   */
  private void setupImageReader() {
    // 2代表ImageReader中最多可以擷取兩幀圖像流
    mImageReader = ImageReader.newInstance(mCaptureSize.getWidth(), mCaptureSize.getHeight(), ImageFormat.JPEG, 1);
    // 設定圖像可用監聽
    mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
      @Override
      public void onImageAvailable(ImageReader reader) {
        // 擷取圖檔
        final Image image = reader.acquireNextImage();
        // 送出任務,儲存圖檔
        mCameraHandler.post(new ImageSaver(image));
        // 更新UI
        getActivity().runOnUiThread(new Runnable() {
          @Override
          public void run() {
            // 擷取位元組緩沖區
            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            // 建立數組之前調用此方法,恢複預設設定
            buffer.rewind();
            // 建立與緩沖區内容大小相同的數組
            byte[] bytes = new byte[buffer.remaining()];
            // 從緩沖區存入位元組數組,讀取完成之後position在末尾
            buffer.get(bytes);
            // 擷取Bitmap圖像
            final Bitmap bitmap =  BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
            // 顯示
            if (null != bitmap) {
              mImageView.setImageBitmap(bitmap);
            }
            
          }
        });
      }
    }, mCameraHandler);
  }
  
  /**
   * 選擇SizeMap中大于并且最接近width和height的size
   * @param sizeMap 可選的尺寸
   * @param width 寬
   * @param height 高
   * @return 最接近width和height的size
   */
  private Size getOptimalSize(Size[] sizeMap, int width, int height) {
    // 建立清單
    List<Size> sizeList = new ArrayList<>();
    // 周遊
    for (Size option : sizeMap) {
      // 判斷寬度是否大于高度
      if (width > height) {
        if (option.getWidth() > width && option.getHeight() > height) {
          sizeList.add(option);
        }
      } else {
        if (option.getWidth() > height && option.getHeight() > width) {
          sizeList.add(option);
        }
      }
    }
    // 判斷存儲Size的清單是否有資料
    if (sizeList.size() > 0) {
      return Collections.min(sizeList, new Comparator<Size>() {
        @Override
        public int compare(Size lhs, Size rhs) {
          return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getWidth() * rhs.getHeight());
        }
      });
    }
    return sizeMap[0];
  }
  
  /**
   * 設定監聽
   */
  private void initListener() {
    mBtnTake.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        takePicture();
      }
    });
  }
  
  /**
   * 預覽
   */
  private void takePreview(){
    // 擷取SurfaceTexture
    SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
    // 設定預設的緩沖大小
    surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
    // 建立Surface
    Surface previewSurface = new Surface(surfaceTexture);
    try {
      // 建立預覽請求
      mCameraCaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
      // 将previewSurface添加到預覽請求中
      mCameraCaptureBuilder.addTarget(previewSurface);
      // 建立會話
      mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, mImageReader.getSurface()), new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
          try {
            // 配置
            CaptureRequest captureRequest = mCameraCaptureBuilder.build();
            // 設置session
            mCameraCaptureSession = session;
            // 設定重複預覽請求
            mCameraCaptureSession.setRepeatingRequest(captureRequest, null, mCameraHandler);
          } catch (CameraAccessException e) {
            e.printStackTrace();
          }
        }
  
        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
          // 配置失敗
        }
      }, mCameraHandler);
    } catch (CameraAccessException e) {
      e.printStackTrace();
    }
  }
  
  /**
   * 拍照
   */
  private void takePicture() {
    try {
      // 設定觸發
      mCameraCaptureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
      mCameraCaptureBuilder.addTarget(mImageReader.getSurface());
      // 拍照
      mCameraCaptureSession.capture(mCameraCaptureBuilder.build(), null, mCameraHandler);
    } catch (CameraAccessException e) {
      Toast.makeText(getActivity(), "異常", Toast.LENGTH_SHORT).show();
      e.printStackTrace();
    }
  }
  
  /**
   * 儲存圖檔任務
   */
  private class ImageSaver implements Runnable {
    /**圖像*/
    private Image mImage;
    ImageSaver(Image image) {
      this.mImage = image;
    }
  
    @Override
    public void run() {
      // 擷取位元組緩沖區
      ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
      // 建立數組之前調用此方法,恢複預設設定--重要
      buffer.rewind();
      // 建立與位元組緩沖區大小相同的位元組數組
      byte[] data = new byte[buffer.remaining()];
      // 将資料讀取位元組數組
      buffer.get(data);
      // 擷取緩存路徑
      String path = getActivity().getExternalCacheDir().getPath();
      // 擷取時間戳
      String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());
      // 檔案名
      String fileName = path + "/IMG_" + timeStamp + ".jpg";
      // 建立檔案輸出流
      FileOutputStream fos = null;
      try {
        // 初始化檔案輸出流
        fos = new FileOutputStream(fileName);
        // 将資料寫入檔案
        fos.write(data, 0, data.length);
        // 重新整理緩沖區
        fos.flush();
      } catch (IOException e) {
        e.printStackTrace();
      } finally {
        if (null != fos) {
          try {
            fos.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      }
    }
  }
}
           

4. 多功能相機

  • 切換攝像頭
/**
   * 後置攝像頭
   */
  private static final int CAMERA_FRONT = CameraCharacteristics.LENS_FACING_FRONT;
  /**
   * 前置攝像頭
   */
  private static final int CAMERA_BACK = CameraCharacteristics.LENS_FACING_BACK;
  /**
   * 照相機ID,辨別前置後置
   */
  private String mCameraId;

  /**
   * 切換前後攝像頭
   */
  private void switchCamera() {
    if (String.valueOf(CAMERA_FRONT).equals(mCameraId)) {
      // 後置
      mCameraId = String.valueOf(CAMERA_BACK);
    } else if (String.valueOf(CAMERA_BACK).equals(mCameraId)) {
      // 前置
      mCameraId = String.valueOf(CAMERA_FRONT);
    }
    closeCamera();
    reOpenCamera();
  }
  
  /**
   * 重新打開攝像頭
   */
  private void reOpenCamera() {
    if (mTextureView.isAvailable()) {
      openCamera();
    } else {
      setTextureListener();
    }
  }
  
  /**
   * 關閉攝像頭
   */
  private void closeCamera() {
    if (null != mCameraCaptureSession) {
      mCameraCaptureSession.close();
      mCameraCaptureSession = null;
    }
    if (null != mCameraDevice) {
      mCameraDevice.close();
      mCameraDevice = null;
    }
    if (null != mImageReader) {
      mImageReader.close();
      mImageReader = null;
    }
  }
           
  • 延時拍攝
/**
   * 無延時
   */
  private static final int DELAY_ZERO = 0;
  /**
   * 延時3秒
   */
  private static final int DELAY_THREE = 3;
  /**
   * 延時10秒
   */
  private static final int DELAY_TEN = 10;
  
  /**
   * 延時拍攝
   */
  private void delayTake() {
    switch (mDelayTime) {
      case DELAY_ZERO:
        mDelayTime = DELAY_THREE;
        break;
      case DELAY_THREE:
        mDelayTime = DELAY_TEN;
        break;
      case DELAY_TEN:
        mDelayTime = DELAY_ZERO;
        break;
    }
    mBtnDelay.setText("延時" + mDelayTime + "秒");
    if (mDelayTime == DELAY_ZERO) {
      takePicture();
    } else {
      // 定時器
      new CountDownTimer(mDelayTime * 1000, 1000) {
        
        @Override
        public void onTick(long millisUntilFinished) {
          mBtnDelay.setText(String.valueOf(millisUntilFinished/1000) + "秒");
        }
        
        @Override
        public void onFinish() {
          mBtnDelay.setText("延時" + mDelayTime + "秒");
          takePicture();
        }
      }.start();
    }
  }

           
  • 切換閃光
/**
   * 閃光辨別--自動開啟
   */
  private static final int FLASH_ZERO = 0;
  /**
   * 閃光辨別--總是開啟
   */
  private static final int FLASH_ONE = 1;
  /**
   * 閃光辨別--關閉
   */
  private static final int FLASH_TWO = 2;
  /**
   * 切換閃光模式
   */
  private void switchFlash() {
    switch(mFlashMode) {
      case FLASH_ZERO:
        mFlashMode = FLASH_ONE;
        mCameraCaptureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
        break;
      case FLASH_ONE:
        mFlashMode = FLASH_TWO;
        mCameraCaptureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
        break;
      case FLASH_TWO:
        mFlashMode = FLASH_ZERO;
        mCameraCaptureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
        // 必須設定
        mCameraCaptureBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
        break;
    }
    try {
      mCameraCaptureSession.setRepeatingRequest(mCameraCaptureBuilder.build(), null, mCameraHandler);
    } catch (CameraAccessException e) {
      e.printStackTrace();
    }
  }
  
           

代碼下載下傳

繼續閱讀