Android Camera——拍照

隕峽發表於2021-04-27

  Camera定義在package android.hardware內,具體用法SDK裡敘述的可清楚了。架構解析什麼的網上也有很多,沒什麼必要講了(你認為我不知道我會說嗎)。

  這篇呢,就整理了下Camera的拍照,其他還木有==

  一、系統相機

  1)呼叫方式

  系統相機的入口Action:MediaStore.ACTION_IMAGE_CAPTURE。只需以startActivityForResult(…)啟動該Activity即可。

  // 呼叫系統相機

  Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

  startActivityForResult(intent, 1);

  2)處理方式

  在onActivityResult(…)中,處理返回資訊。

  protected void onActivityResult(int requestCode, int resultCode, Intent data) {

  if (1 == requestCode) { // 系統相機返回處理

  if (resultCode == Activity.RESULT_OK) {

  Bitmap cameraBitmap = (Bitmap) data.getExtras().get("data");

  …… // 處理影像

  }

  takeBtn1.setClickable(true);

  }

  super.onActivityResult(requestCode, resultCode, data);

  }

  二、自定義相機

  1)照相預覽

  繼承SufaceView寫自己的預覽介面,繼而放到你的照相Activity的佈局裡。這裡面有個相機拍照監聽介面,用於在Activity裡再處理這些操作。

  public class CameraPreview extends SurfaceView implements

  SurfaceHolder.Callback {

  /** LOG標識 */

  // private static final String TAG = "CameraPreview";

  /** 解析度 */

  public static final int WIDTH = 1024;

  public static final int HEIGHT = 768;

  /** 監聽介面 */

  private OnCameraStatusListener listener;

  private SurfaceHolder holder;

  private Camera camera;

  // 建立一個PictureCallback物件,並實現其中的onPictureTaken方法

  private PictureCallback pictureCallback = new PictureCallback() {

  // 該方法用於處理拍攝後的照片資料

  @Override

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

  // 停止照片拍攝

  camera.stopPreview();

  camera = null;

  // 呼叫結束事件

  if (null != listener) {

  listener.onCameraStopped(data);

  }

  }

  };

  // Preview類的構造方法

  public CameraPreview(Context context, AttributeSet attrs) {

  super(context, attrs);

  // 獲得SurfaceHolder物件

  holder = getHolder();

  // 指定用於捕捉拍照事件的SurfaceHolder.Callback物件

  holder.addCallback(this);

  // 設定SurfaceHolder物件的型別

  holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

  }

  // 在surface建立時激發

  public void surfaceCreated(SurfaceHolder holder) {

  // Log.e(TAG, "==surfaceCreated==");

  // 獲得Camera物件

  camera = Camera.open();

  try {

  // 設定用於顯示拍照攝像的SurfaceHolder物件

  camera.setPreviewDisplay(holder);

  } catch (IOException e) {

  e.printStackTrace();

  // 釋放手機攝像頭

  camera.release();

  camera = null;

  }

  }

  // 在surface銷燬時激發

  public void surfaceDestroyed(SurfaceHolder holder) {

  // Log.e(TAG, "==surfaceDestroyed==");

  // 釋放手機攝像頭

  camera.release();

  }

  // 在surface的大小發生改變時激發

  public void surfaceChanged(final SurfaceHolder holder, int format, int w,

  int h) {

  // Log.e(TAG, "==surfaceChanged==");

  try {

  // 獲取照相機引數

  Camera.Parameters parameters = camera.getParameters();

  // 設定照片格式

  parameters.setPictureFormat(PixelFormat.JPEG);

  // 設定預瀏尺寸

  parameters.setPreviewSize(WIDTH, HEIGHT);

  // 設定照片解析度

  parameters.setPictureSize(WIDTH, HEIGHT);

  // 設定照相機引數

  camera.setParameters(parameters);

  // 開始拍照

  camera.startPreview();

  } catch (Exception e) {

  e.printStackTrace();

  }

  }

  // 停止拍照,並將拍攝的照片傳入PictureCallback介面的onPictureTaken方法

  public void takePicture() {

  // Log.e(TAG, "==takePicture==");

  if (camera != null) {

  // 自動對焦

  camera.autoFocus(new AutoFocusCallback() {

  @Override

  public void onAutoFocus(boolean success, Camera camera) {

  if (null != listener) {

  listener.onAutoFocus(success);

  }

  // 自動對焦成功後才拍攝

  if (success) {

  camera.takePicture(null, null, pictureCallback);

  }

  }

  });

  }

  }

  // 設定監聽事件

  public void setOnCameraStatusListener(OnCameraStatusListener listener) {

  this.listener = listener;

  }

  /**

  * 相機拍照監聽介面

  */

  public interface OnCameraStatusListener {

  // 相機拍照結束事件

  void onCameraStopped(byte[] data);

  // 拍攝時自動對焦事件

  void onAutoFocus(boolean success);

  }

  }

  2)照相活動

  就是我們自己做的照相Activity了。完成後呼叫自己的相機,也就是跳轉入這個Activity。這裡面,照片以自定義路徑的形式存入的媒體庫。

  public class CameraActivity extends Activity implements

  CameraPreview.OnCameraStatusListener {

  public static final Uri IMAGE_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

  public static final String PATH = Environment.getExternalStorageDirectory()

  .toString() + "/AndroidMedia/";

  private CameraPreview mCameraPreview;

  private ImageView focusView;

  private boolean isTaking = false; // 拍照中

  @Override

  public void onCreate(Bundle savedInstanceState) {

  super.onCreate(savedInstanceState);

  // 設定橫屏

  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

  // 設定全屏

  requestWindowFeature(Window.FEATURE_NO_TITLE);

  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

  WindowManager.LayoutParams.FLAG_FULLSCREEN);

  // 設定佈局檢視

  setContentView(R.layout.camera);

  // 照相預覽介面

  mCameraPreview = (CameraPreview) findViewById(R.id.preview);

  mCameraPreview.setOnCameraStatusListener(this);

  // 焦點圖片

  focusView = (ImageView) findViewById(R.id.focusView);

  }

  /**

  * 觸屏事件

  */

  @Override

  public boolean onTouchEvent(MotionEvent event) {

  if (event.getAction() == MotionEvent.ACTION_DOWN && !isTaking) {

  isTaking = true;

  mCameraPreview.takePicture();

  }

  return super.onTouchEvent(event);

  }

  /**

  * 儲存影像並將資訊新增入媒體資料庫

  */

  private Uri insertImage(ContentResolver cr, String name, long dateTaken,

  String directory, String filename, Bitmap source, byte[] jpegData) {

  OutputStream outputStream = null;

  String filePath = directory + filename;

  try {

  File dir = new File(directory);

  if (!dir.exists()) {

  dir.mkdirs();

  }

  File file = new File(directory, filename);

  if (file.createNewFile()) {

  outputStream = new FileOutputStream(file);

  if (source != null) {

  source.compress(CompressFormat.JPEG, 75, outputStream);

  } else {

  outputStream.write(jpegData);

  }

  }

  } catch (FileNotFoundException e) {

  e.printStackTrace();

  return null;

  } catch (IOException e) {

  e.printStackTrace();

  return null;

  } finally {

  if (outputStream != null) {

  try {

  outputStream.close();

  } catch (Throwable t) {

  }

  }

  }

  ContentValues values = new ContentValues(7);

  values.put(MediaStore.Images.Media.TITLE, name);

  values.put(MediaStore.Images.Media.DISPLAY_NAME, filename);

  values.put(MediaStore.Images.Media.DATE_TAKEN, dateTaken);

  values.put(MediaStore.Images.Media.MIME_TYPE, "p_w_picpath/jpeg");

  values.put(MediaStore.Images.Media.DATA, filePath);

  return cr.insert(IMAGE_URI, values);

  }

  /**

  * 相機拍照結束事件

  */

  @Override

  public void onCameraStopped(byte[] data) {

  Log.e("onCameraStopped", "==>

  // 建立影像

  Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

  // 系統時間

  long dateTaken = System.currentTimeMillis();

  // 影像名稱

  String filename = DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken)

  .toString() + ".jpg";

  // 儲存影像(PATH目錄)

  Uri uri = insertImage(getContentResolver(), filename, dateTaken, PATH,

  filename, bitmap, data);

  // 返回結果

  Intent intent = getIntent();

  intent.putExtra("uriStr", uri.toString());

  intent.putExtra("dateTaken", dateTaken);

  // intent.putExtra("filePath", PATH + filename);

  // intent.putExtra("orientation", orientation); // 拍攝方向

  setResult(20, intent);

  // 關閉當前Activity

  finish();

  }

  /**

  * 拍攝時自動對焦事件

  */

  @Override

  public void onAutoFocus(boolean success) {

  // 改變對焦狀態影像

  if (success) {

  focusView.setImageResource(R.drawable.focus2);

  } else {

  focusView.setImageResource(R.drawable.focus1);

  Toast.makeText(this, "焦距不準,請重拍!", Toast.LENGTH_SHORT).show();

  isTaking = false;

  }

  }

  }

  3)相機呼叫&處理

  // 呼叫自定義相機

  Intent intent = new Intent(this, CameraActivity.class);

  startActivityForResult(intent, 2);

  protected void onActivityResult(int requestCode, int resultCode, Intent data) {

  if (2 == requestCode) { // 自定義相機返回處理

  // 拍照成功後,響應碼是20

  if (resultCode == 20) {

  Bundle bundle = data.getExtras();

  // 獲得照片uri

  Uri uri = Uri.parse(bundle.getString("uriStr"));

  // 獲得拍照時間

  long dateTaken = bundle.getLong("dateTaken");

  try {

  // 從媒體資料庫獲取該照片

  Bitmap cameraBitmap = MediaStore.Images.Media.getBitmap(

  getContentResolver(), uri);

  previewBitmap(cameraBitmap); // 預覽影像

  // 從媒體資料庫刪除該照片(按拍照時間)

  getContentResolver().delete(

  CameraActivity.IMAGE_URI,

  MediaStore.Images.Media.DATE_TAKEN + "="

  + String.valueOf(dateTaken), null);

  } catch (Exception e) {

  e.printStackTrace();

  }

  }

  takeBtn2.setClickable(true);

  }

  super.onActivityResult(requestCode, resultCode, data);

  }


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69920960/viewspace-2770062/,如需轉載,請註明出處,否則將追究法律責任。

相關文章