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

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

两个TextView是用来显示提示信息和倒计时的秒数的

<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. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. Android疑问1——Handler的removeCallbacks方法无效?(已经明白了)
  3. Android(安卓)FFmpeg系列——3 C多线程使用
  4. 【Android】java.lang.AssertionError use looper thread, must
  5. Andriod中的Handler机制
  6. Android(安卓)AsyncTask基础知识整理
  7. Android解耦库EventBus的使用和源码分析
  8. Android(安卓)SurfaceFlinger服务启动过程源码分析1
  9. android通过线程实现逐行显示信息

随机推荐

  1. 巧用AsyncTask的onProgressUpdate回调
  2. Android网络相关---上网流程
  3. Android之Adapter用法总结
  4. Gradle 发布共享库——如何通过Gradle发
  5. Android音频系统探究——从SoundPool到Au
  6. Android(安卓)Vector矢量图
  7. Android(安卓)下的视频播放器faplayer 编
  8. 让你自己写的Android的Launcher成为系统
  9. Android中measure过程、WRAP_CONTENT详解
  10. 神们自己