Android camera camera operation package

The camera function that comes with Android is often used in the project. So I made a package, CameraUtil.java class.

It's simple to use again, and it can maximize the reuse and improve efficiency.

I like to encapsulate commonly used functional modules the most, because an excellent code idea is to pursue maximum reuse and high efficiency. Recommend "Refactoring" and "Programmer's Practice" books. Don't think that some of these books are relatively empty in theory. It is better to read books such as so and so on actual combat. In fact, this kind of book affects people's thinking, and the change of thinking is far more important than you learn a few more lines of code.

Good packaging can make you do more with less, and implement applications as quickly as building blocks. Why do some big cows make things fast? There is no other reason, it must be the accumulation of many wheels that can be reused.

The encapsulated CameraUtil class is very simple to use.

First come the effect picture:

How easy is it to use the encapsulated CameraUtil class?

 if (cameraUtil == null){
            int rotation = getWindowManager().getDefaultDisplay().getRotation();
            cameraUtil = new CameraUtil(surfaceView, 0,rotation, takeButton, onPictureListener);
            cameraUtil.start();
        }

Just pass in five parameters. The first is the preview interface surfaceView, the second parameter is the camera ID, the default is 0. The third parameter is the angle of image rotation. The fourth parameter is the button for taking pictures. onPictureListener is the callback processing when the photo is taken.

/*
     * 拍照信息回调
     */
        OnPictureListener onPictureListener = new OnPictureListener() {
        @Override
        public void getPicture(Drawable drawable) {
            //getCameraPicture(drawable);
            final Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
            Log.d(TAG,"take picture bitmap size kb:"+bitmap.getByteCount()/1024);
            DataConstant.photo = Utils.bitmapToString(bitmap);
            File tempFile = new File("/sdcard/temp0.png");
            try {
                FileOutputStream fos = new FileOutputStream(tempFile);
                bitmap.compress(Bitmap.CompressFormat.PNG,100,fos);
                //写入,这里会卡顿,因为图片较大
                fos.flush();
                //记得要关闭写入流
                fos.close();
            }catch (Exception ex){
                ex.printStackTrace();
            }
}

The package is as follows:

package com.newcapec.fkrobot.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import com.newcapec.fkrobot.app.App;
import com.newcapec.fkrobot.interf.OnPictureListener;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @author : yangyognzhen
 * @date :2020/7/11 14:19
 * @description:
 **/
public class CameraUtil {
    private String TAG = this.getClass().getSimpleName();

    //相机和相机预览mSurfaceView
    private Camera mCamera;
    private SurfaceView mSurfaceView;
    private SurfaceHolder mHolder;

    //摄像头支持的分辨率
    private Camera.Size mPreviewSize;
    private List mSupportedPreviewSizes;

    //private Activity activity;
    private View button;
    private int mCameraId;
    private int additionalRotation;
    private int displayOrientation = 0;
    private int rotation;

    private OnPictureListener onFinishListener;
    private static CameraUtil _instance;


    public static CameraUtil getInstance(SurfaceView surfaceView, int cameraId, int rotation, View button, OnPictureListener onFinishListener) {
        if (_instance == null)
            _instance = new CameraUtil(surfaceView,cameraId,rotation,button,onFinishListener);
        return _instance;
    }

    public CameraUtil(SurfaceView surfaceView, int cameraId, int rotation, View button, OnPictureListener onFinishListener){
        this.mSurfaceView = surfaceView;
        this.button = button;
        this.onFinishListener = onFinishListener;
        mCameraId = cameraId;
        this.rotation = rotation;
        //初始化相机预览及回调
        initData(cameraId);
    }

    private void initData(int id) {
        //增加surfaceview回调
        mHolder= mSurfaceView.getHolder();
        mHolder.addCallback(callback);
        //mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

       mPreviewSize=getPreviewSize(id);
       // mCamera.setDisplayOrientation(270);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Camera.Parameters parameters = mCamera.getParameters();
                parameters.setJpegQuality(100);  //生成图像的质量
                mCamera.setParameters(parameters);
                parameters.setPictureFormat(ImageFormat.JPEG);
                parameters.setPictureSize(640, 480); //生成图像的风辨率
                mCamera.setParameters(parameters);
//                int ro = displayOrientation+90;
//                if(ro >= 360){
//                    ro = 0;
//                }
                parameters.setRotation(displayOrientation);  //生成的图像旋转90度
                mCamera.setParameters(parameters);
                //拍照的提示音
                shootSound();
                mCamera.takePicture(null,null, new Camera.PictureCallback() {
                    @Override
                    public void onPictureTaken(byte[] data, Camera camera) {
                        // 主要就是将图片转化成drawable,设置为固定区域的背景(展示图片),当然也可以直接在布局文件里放一个surfaceView供使用。
                        ByteArrayInputStream bais = new ByteArrayInputStream(data);
                        Drawable d = BitmapDrawable.createFromStream(bais, Environment
                                .getExternalStorageDirectory().getAbsolutePath()
                                + "/img.jpeg");
                        Bitmap bitmap = ((BitmapDrawable) d).getBitmap();
                        Log.d(TAG,"fk picture bitmap size kb:"+bitmap.getByteCount()/1024);
                        File tempFile = new File("/sdcard/temp.png");
                        try {
                            FileOutputStream fos = new FileOutputStream(tempFile);
                            fos.write(data);
                            fos.close();
                        }catch (Exception ex){
                            ex.printStackTrace();
                        }
                        if(onFinishListener != null){
                            onFinishListener.getPicture(d);
                        }
                        mCamera.startPreview();
                        try {
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
    }

    private Camera.Size getPreviewSize(int id){
        mCamera = Camera.open(id);
       // mCamera.setDisplayOrientation(270);
        displayOrientation = getCameraOri(rotation);
        Log.e(TAG,"camera displayOrientation:"+displayOrientation);
        mCamera.setDisplayOrientation(displayOrientation);
        setCamera(mCamera);
        if(mCamera!=null){
            Camera.Parameters parameters = mCamera.getParameters();
             //获取摄像头支持的分辨率
            List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
            //遍历输出摄像头支持的所有分辨率
            for(Camera.Size s: sizes){
                Log.e(TAG,"size====="+s.width+"X"+s.height);
            }
            Camera.Size optimalSize = Utils.getOptimalPreviewSize(sizes, sizes.get(0).height, sizes.get(0).width);
            return optimalSize;
        }
        return null;
    }

    private void setCamera(Camera camera) {
        mCamera = camera;
        if (mCamera != null) {
            mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
        }

        try {
            camera.setPreviewDisplay(mHolder);
        } catch (IOException exception) {
            Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
        }
        Camera.Parameters parameters = camera.getParameters();

        // 设置相片格式
        parameters.setJpegQuality(100);  //生成图像的质量
        mCamera.setParameters(parameters);
        parameters.setPictureFormat(ImageFormat.JPEG);
        //parameters.setPreviewFormat(ImageFormat.YV12);
        //parameters.setPictureFormat(ImageFormat.FLEX_RGB_888);
        // 设置预览大小
        //parameters.setPreviewSize(640, 480);
        parameters.setPictureSize(640, 480); //生成图像的风辨率
        mCamera.setParameters(parameters);
        //List sizes = parameters.getSupportedPreviewSizes();
        //Camera.Size optimalSize = Utils.getOptimalPreviewSize(sizes, 1920, 1080);
        //parameters.setPreviewSize(optimalSize.width, optimalSize.height);
        //设置摄像头翻转角度
        //parameters.setRotation(90);
        //设置镜像效果,支持的值为flip-mode-values=off,flip-v,flip-h,flip-vh;
        //flip-mode-values规定了翻转(镜像)模式的取值只能为off(关闭),flip-v(竖直翻转),flip-h(水平翻转),flip-vh(竖直+水平翻转)
       //parameters.set("preview-flip", "flip-vh");
       camera.setParameters(parameters);
    }


    SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                if (mCamera != null) {
                    //建立预览界面
                    mCamera.setPreviewDisplay(holder);
                    //mCamera.setDisplayOrientation(270);
                }
            } catch (IOException exception) {
                Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            if(mCamera != null){
                Camera.Parameters parameters = mCamera.getParameters();
                parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 1连续对焦
                setDispaly(parameters, mCamera);
                //开始预览
                mCamera.startPreview();
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            if (mCamera != null) {
                mCamera.stopPreview();
            }
        }
    };

    /*
     * 控制图像的正确显示方向
     */
    private void setDispaly(Camera.Parameters parameters, Camera camera) {
        if (Integer.parseInt(Build.VERSION.SDK) >= 8) {
           // setDisplayOrientation(camera, 0);
        } else {
           // parameters.setRotation(90);
        }
    }

    private int getCameraOri(int rotation) {
        int degrees = rotation * 90;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
            default:
                break;
        }
        additionalRotation /= 90;
        additionalRotation *= 90;
        degrees += additionalRotation;
        int result;
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(mCameraId, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;
        } else {
            result = (info.orientation - degrees + 360) % 360;
        }
        return result;
    }

    /*
     * 实现的图像的正确显示
     */
    private void setDisplayOrientation(Camera camera, int i) {
        Method downPolymorphic;
        try {
            downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[]{int.class});
            if (downPolymorphic != null) {
                downPolymorphic.invoke(camera, new Object[]{i});
            }
        } catch (Exception e) {
            Log.e("Came_e", "图像出错");
        }
    }

    /**
     *   播放系统拍照声音
     */
    public void shootSound() {
        MediaPlayer shootMP;
        AudioManager meng = (AudioManager) App.getContext().getSystemService(Context.AUDIO_SERVICE);
        int volume = meng.getStreamVolume( AudioManager.STREAM_NOTIFICATION);
        if (volume != 0) {
            shootMP = MediaPlayer.create(App.getContext(), Uri.parse("file:///system/media/audio/ui/camera_click.ogg"));
            shootMP.start();
        }
    }

    /**
     * 开启拍照
     */
    public void start() {
        synchronized (this) {
            if (mCamera != null) {
                return;
            }
            //initData(0);
            mCamera.startPreview();
        }
    }

    /**
     * 停掉摄像头拍照
     */
    public void stop() {
        synchronized (this) {
            if (mCamera == null) {
                return;
            }
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
            Log.e(TAG,"释放摄像头");
        }
    }

}

 

Guess you like

Origin blog.csdn.net/qq8864/article/details/110240637