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

转载于:https://www.cnblogs.com/yunfang/p/5023227.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值