Android自定义相机实现定时拍照功能

#技术教程 发布时间: 2026-01-18

这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能。

首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件:

activity_main.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" > 
 
 <SurfaceView 
  android:id="@+id/surface_view" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" /> 
 
 <RelativeLayout 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  android:orientation="vertical" > 
 
  <ImageView 
   android:id="@+id/start" 
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
   android:layout_centerHorizontal="true" 
   android:layout_alignParentBottom="true" 
   android:layout_marginBottom="10dp" 
   android:src="@drawable/capture"/> 
 
  <TextView 
   android:id="@+id/count_down" 
   android:layout_width="match_parent" 
   android:layout_height="match_parent" 
   android:layout_gravity="center" 
   android:gravity="center" 
   android:textSize="80sp"/> 
 </RelativeLayout> 
</FrameLayout> 

MainActivity.java

package com.jackie.timercamera; 
 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Matrix; 
import android.hardware.Camera; 
import android.media.AudioManager; 
import android.media.MediaPlayer; 
import android.net.Uri; 
import android.os.Bundle; 
import android.os.Environment; 
import android.os.Handler; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.widget.ImageView; 
import android.widget.TextView; 
 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
 
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback, 
  View.OnClickListener, Camera.PictureCallback { 
 private SurfaceView mSurfaceView; 
 private ImageView mIvStart; 
 private TextView mTvCountDown; 
 
 private SurfaceHolder mHolder; 
 
 private Camera mCamera; 
 
 private Handler mHandler = new Handler(); 
 
 private int mCurrentTimer = 10; 
 
 private boolean mIsSurfaceCreated = false; 
 private boolean mIsTimerRunning = false; 
 
 private static final int CAMERA_ID = 0; //后置摄像头 
// private static final int CAMERA_ID = 1; //前置摄像头 
 private static final String TAG = MainActivity.class.getSimpleName(); 
 
 @Override 
 protected void onCreate(Bundle savedInstanceState) { 
  super.onCreate(savedInstanceState); 
  setContentView(R.layout.activity_main); 
 
  initView(); 
  initEvent(); 
 } 
 
 @Override 
 protected void onPause() { 
  super.onPause(); 
 
  stopPreview(); 
 } 
 
 private void initView() { 
  mSurfaceView = (SurfaceView) findViewById(R.id.surface_view); 
  mIvStart = (ImageView) findViewById(R.id.start); 
  mTvCountDown = (TextView) findViewById(R.id.count_down); 
 } 
 
 private void initEvent() { 
  mHolder = mSurfaceView.getHolder(); 
  mHolder.addCallback(this); 
 
  mIvStart.setOnClickListener(this); 
 } 
 
 @Override 
 public void surfaceCreated(SurfaceHolder holder) { 
  mIsSurfaceCreated = true; 
 } 
 
 @Override 
 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
  startPreview(); 
 } 
 
 @Override 
 public void surfaceDestroyed(SurfaceHolder holder) { 
  mIsSurfaceCreated = false; 
 } 
 
 private void startPreview() { 
  if (mCamera != null || !mIsSurfaceCreated) { 
   Log.d(TAG, "startPreview will return"); 
   return; 
  } 
 
  mCamera = Camera.open(CAMERA_ID); 
 
  Camera.Parameters parameters = mCamera.getParameters(); 
  int width = getResources().getDisplayMetrics().widthPixels; 
  int height = getResources().getDisplayMetrics().heightPixels; 
  Camera.Size size = getBestPreviewSize(width, height, parameters); 
  if (size != null) { 
   //设置预览分辨率 
   parameters.setPreviewSize(size.width, size.height); 
   //设置保存图片的大小 
   parameters.setPictureSize(size.width, size.height); 
  } 
 
  //自动对焦 
  parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 
  parameters.setPreviewFrameRate(20); 
 
  //设置相机预览方向 
  mCamera.setDisplayOrientation(90); 
 
  mCamera.setParameters(parameters); 
 
  try { 
   mCamera.setPreviewDisplay(mHolder); 
  } catch (Exception e) { 
   Log.d(TAG, e.getMessage()); 
  } 
 
  mCamera.startPreview(); 
 } 
 
 private void stopPreview() { 
  //释放Camera对象 
  if (mCamera != null) { 
   try { 
    mCamera.setPreviewDisplay(null); 
    mCamera.stopPreview(); 
    mCamera.release(); 
    mCamera = null; 
   } catch (Exception e) { 
    Log.e(TAG, e.getMessage()); 
   } 
  } 
 } 
 
 private Camera.Size getBestPreviewSize(int width, int height, 
           Camera.Parameters parameters) { 
  Camera.Size result = null; 
 
  for (Camera.Size size : parameters.getSupportedPreviewSizes()) { 
   if (size.width <= width && size.height <= height) { 
    if (result == null) { 
     result = size; 
    } else { 
     int resultArea = result.width * result.height; 
     int newArea = size.width * size.height; 
 
     if (newArea > resultArea) { 
      result = size; 
     } 
    } 
   } 
  } 
 
  return result; 
 } 
 
 @Override 
 public void onClick(View v) { 
  switch (v.getId()) { 
   case R.id.start: 
    if (!mIsTimerRunning) { 
     mIsTimerRunning = true; 
     mHandler.post(timerRunnable); 
    } 
    break; 
  } 
 } 
 
 private Runnable timerRunnable = new Runnable() { 
  @Override 
  public void run() { 
   if (mCurrentTimer > 0) { 
    mTvCountDown.setText(mCurrentTimer + ""); 
 
    mCurrentTimer--; 
    mHandler.postDelayed(timerRunnable, 1000); 
   } else { 
    mTvCountDown.setText(""); 
 
    mCamera.takePicture(null, null, null, MainActivity.this); 
    playSound(); 
 
    mIsTimerRunning = false; 
    mCurrentTimer = 10; 
   } 
  } 
 }; 
 
 @Override 
 public void onPictureTaken(byte[] data, Camera camera) { 
  try { 
   FileOutputStream fos = new FileOutputStream(new File 
     (Environment.getExternalStorageDirectory() + File.separator + 
       System.currentTimeMillis() + ".png")); 
 
   //旋转角度,保证保存的图片方向是对的 
   Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); 
   Matrix matrix = new Matrix(); 
   matrix.setRotate(90); 
   bitmap = Bitmap.createBitmap(bitmap, 0, 0, 
     bitmap.getWidth(), bitmap.getHeight(), matrix, true); 
   bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); 
   fos.flush(); 
   fos.close(); 
  } catch (FileNotFoundException e) { 
   e.printStackTrace(); 
  } catch (IOException e) { 
   e.printStackTrace(); 
  } 
 
  mCamera.startPreview(); 
 } 
 
 /** 
  * 播放系统拍照声音 
  */ 
 public void playSound() { 
  MediaPlayer mediaPlayer = null; 
  AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 
  int volume = audioManager.getStreamVolume( AudioManager.STREAM_NOTIFICATION); 
 
  if (volume != 0) { 
   if (mediaPlayer == null) 
    mediaPlayer = MediaPlayer.create(this, 
      Uri.parse("file:///system/media/audio/ui/camera_click.ogg")); 
   if (mediaPlayer != null) { 
    mediaPlayer.start(); 
   } 
  } 
 } 
} 

有两点需要注意:对于Camera来说,默认是横屏的,所以预览的时候和图片保存的时候都是横屏的,需要调整角度。

设置相机预览方法:

//设置相机预览方向
mCamera.setDisplayOrientation(90);

保存图片的时候调整角度:

效果图如下:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。




上一篇 : Ajax跨域实现代码(后台jsp)

下一篇 : SQL如何生成连续日期_时间维度补齐方法讲解【教程】

推荐阅读

电话:400 76543 55
邮箱:915688610@qq.com
品牌营销
客服微信
搜索营销
公众号
©  丽景创新 版权所有 赣ICP备2024032158号 
宜昌市隼壹珍商贸有限公司 宜昌市隼壹珍商贸有限公司 宜昌市隼壹珍商贸有限公司 宜昌市隼壹珍商贸有限公司 宜昌市隼壹珍商贸有限公司 宜昌市隼壹珍商贸有限公司 宜昌市隼壹珍商贸有限公司 宜昌市隼壹珍商贸有限公司 宜昌市隼壹珍商贸有限公司 宜昌市隼壹珍商贸有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 内江振祥营销策划有限公司 恩施州毯滚百货有限公司 恩施州毯滚百货有限公司 襄阳市蜂欢商贸有限公司 襄阳市蜂欢商贸有限公司 恩施州换冯百货有限公司 恩施州换冯百货有限公司 恩施州健提百货有限公司 恩施州健提百货有限公司 西安益零商贸有限公司 西安益零商贸有限公司 南奥教育 南奥教育 南奥教育 南奥教育 南昌市南奥教育咨询有限公司 南昌市南奥教育咨询有限公司 南昌市南奥教育咨询有限公司 南昌市南奥教育咨询有限公司 南昌市南奥教育咨询有限公司 南昌市南奥教育咨询有限公司 南昌市南奥教育咨询有限公司 南昌市南奥教育咨询有限公司 南奥教育网 南奥教育网 南奥教育网 南奥教育网 南奥学习网 南奥学习网 南奥学习网 南奥学习网 南奥教育 南奥教育 南奥留学记 南奥留学记 南奥教育 南奥教育 南昌市南奥教育咨询有限公司 南昌市南奥教育咨询有限公司 南昌市南奥教育咨询有限公司 南昌市南奥教育咨询有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 南昌壹佳企网络通信有限公司 广照天下广告 广照天下广告 广照天下广告策划 广照天下广告策划 广照天下 广照天下 广照天下 广照天下 广照天下 广照天下 广照天下广告策划 广照天下广告策划 广照天下广告策划 广照天下广告策划 南昌市广照天下广告策划有限公司 南昌市广照天下广告策划有限公司 南昌市广照天下广告策划有限公司 南昌市广照天下广告策划有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 宿州市腾雀网络科技有限公司 九江市云仁商务咨询有限公司 九江市云仁商务咨询有限公司 九江市云仁商务咨询有限公司 九江市云仁商务咨询有限公司 九江市云仁商务咨询有限公司 九江市云仁商务咨询有限公司 九江市云仁商务咨询有限公司 九江市云仁商务咨询有限公司 九江市云仁商务咨询有限公司 九江市云仁商务咨询有限公司
品牌营销
专业SEO优化
添加左侧专家微信
获取产品详细报价方案