• Android—实现自定义相机倒计时拍照


    这篇博客为大家介绍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;
                }
            }
        }

    希望大家理解核心代码的详细注释,欢迎提供意见,希望能给大家带来帮助,谢谢!

    源码:http://pan.baidu.com/s/1kVSBEK3

  • 相关阅读:
    DOM操作——JavaScript怎样添加、移除、移动、复制、创建和查找节点
    Vue入门实战: 小白总结
    localStorage如何设置过期时间?
    北京游记-2019年小总结
    寒假宅家微记录
    SpringBoot 使用 swagger
    校园旧书交易交换平台
    Html 文件内容展示 图片展示
    Python 简易Cmd控制
    Python 多线程实现循环打印 abc
  • 原文地址:https://www.cnblogs.com/yunfang/p/5023227.html
Copyright © 2020-2023  润新知