Android Camera拍照

Android 相机拍照的注意事项和基本使用请点击——Android Camera开发之基础知识篇

本文主要介绍Camera在项目中的代码实现:(经测试可用)

    

package com.wj.shoes.shortvideo.view.fragment.photo;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.ScaleAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;

import com.wj.shoes.R;
import com.wj.shoes.common.MyApplication;
import com.wj.shoes.shortvideo.utils.ImageUtils;
import com.wj.shoes.shortvideo.utils.camera.CameraHelper;
import com.wj.shoes.shortvideo.utils.camera.FileUtils;
import com.wj.shoes.shortvideo.utils.camera.IOUtil;
import com.wj.shoes.shortvideo.utils.camera.StringUtils;
import com.wj.shoes.shortvideo.view.activity.shortvideo.circle_activity_camera_sticker.CircleCameraStickerActivity;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import butterknife.ButterKnife;

/**
 * 照相
 */

public class PhotoFragment extends Fragment implements View.OnClickListener, View.OnTouchListener{
    private View mView;
    //预览画面
    private SurfaceView sfv_show_frame;
    //拍照
    private ImageView iv_photograph;
    //切换摄像头
    private ImageView iv_switch_camera;
    //切换闪光灯模式
    private ImageView iv_flash_lamp;
    private CameraHelper mCameraHelper;
    private View v_focus_index;
    private Camera cameraInst = null;
    private Camera.Parameters parameters = null;
    private int PHOTO_SIZE = 2000;
    //1是前置 0是后置
    private int mCurrentCameraId = 0;
    private Bundle bundle = null;
    //前后置摄像头切换
    private float pointX, pointY;
    static final int FOCUS = 1;// 聚焦
    static final int ZOOM = 2;// 缩放
    private int mode; //0是聚焦 1是放大
    private float dist;
    private Handler handler = new Handler();
    private SurfaceHolder surfaceHolder=null;
    private SurfaceCallback surfaceCallback=null;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if (mView == null) {
            mView = inflater.inflate(R.layout.mgx_fragment_photo, container, false);
            mCameraHelper = new CameraHelper(getActivity());
            checkCameraHardware(getActivity());
        }
        return mView;
    }

    //检查该设备是否有摄像头
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            initView();
            return true;
        } else {
            Toast.makeText(getActivity(), "该设备没有摄像头", Toast.LENGTH_LONG).show();
            return false;
        }
    }

    private void initView() {
        sfv_show_frame = (SurfaceView) mView.findViewById(R.id.sfv_show_frame);
        sfv_show_frame.setOnTouchListener(this);
        sfv_show_frame.setOnClickListener(this);
        iv_photograph = (ImageView) mView.findViewById(R.id.iv_photograph);
        iv_photograph.setOnClickListener(this);
        iv_switch_camera = (ImageView) mView.findViewById(R.id.iv_switch_camera);
        iv_switch_camera.setOnClickListener(this);
        iv_flash_lamp = (ImageView) mView.findViewById(R.id.iv_flash_lamp);
        iv_flash_lamp.setOnClickListener(this);
        v_focus_index = (View) mView.findViewById(R.id.v_focus_index);
        v_focus_index.setOnClickListener(this);

        //初始化相机
        surfaceHolder = sfv_show_frame.getHolder();
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceHolder.setKeepScreenOn(true);
        sfv_show_frame.setFocusable(true);
        //TRIM_MEMORY_BACKGROUND ComponentCallbacks2  TRIM_MEMORY_BACKGROUND=40
        sfv_show_frame.setBackgroundColor(40);
        SurfaceCallback surfaceCallback=new SurfaceCallback();
        //为SurfaceView的句柄添加一个回调函数
        sfv_show_frame.getHolder().addCallback(surfaceCallback);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            //拍照
            case R.id.iv_photograph:
                cameraInst.takePicture(null, null, new MyPictureCallback());
                break;
            //切换摄像头
            case R.id.iv_switch_camera:
                switchCamera();
                break;
            //切换闪光灯
            case R.id.iv_flash_lamp:
                turnLight(cameraInst);
                break;
            //点击显示画面
            case R.id.sfv_show_frame:
                focusFrame();
                break;
        }
    }

    //聚焦框
    private void focusFrame() {
        try {
            pointFocus((int) pointX, (int) pointY);
        } catch (Exception e) {
            e.printStackTrace();
        }
        FrameLayout.LayoutParams layout = new FrameLayout.LayoutParams(v_focus_index.getLayoutParams());
        layout.setMargins((int) pointX - 60, (int) pointY - 60, 0, 0);
        //surface view初始化时大小的设置
        v_focus_index.setLayoutParams(layout);
        v_focus_index.setVisibility(View.VISIBLE);
        ScaleAnimation sa = new ScaleAnimation(3f, 1f, 3f, 1f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
        sa.setDuration(800);
        v_focus_index.startAnimation(sa);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                v_focus_index.setVisibility(View.INVISIBLE);
            }
        }, 800);
    }

    /**
     * 缩放
     *
     * @param view
     * @param motionEvent
     * @return
     */
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
            // 主点按下
            case MotionEvent.ACTION_DOWN:
                pointX = motionEvent.getX();
                pointY = motionEvent.getY();
                mode = FOCUS;
                break;
            // 副点按下
            case MotionEvent.ACTION_POINTER_DOWN:
                dist = spacing(motionEvent);
                // 如果连续两点距离大于10,则判定为多点模式
                if (spacing(motionEvent) > 10f) {
                    mode = ZOOM;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mode = FOCUS;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == FOCUS) {
                    //pointFocus((int) event.getRawX(), (int) event.getRawY());
                } else if (mode == ZOOM) {
                    float newDist = spacing(motionEvent);
                    if (newDist > 10f) {
                        float tScale = (newDist - dist) / dist;
                        if (tScale < 0) {
                            tScale = tScale * 10;
                        }
                        addZoomIn((int) tScale);
                    }
                }
                break;
        }
        return false;
    }

    /**
     * 两点的距离
     */
    private float spacing(MotionEvent event) {
        if (event == null) {
            return 0;
        }
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }

    //放大缩小
    int curZoomValue = 0;

    private void addZoomIn(int delta) {

        try {
            Camera.Parameters params = cameraInst.getParameters();
            Log.d("Camera", "Is support Zoom " + params.isZoomSupported());
            if (!params.isZoomSupported()) {
                return;
            }
            curZoomValue += delta;
            if (curZoomValue < 0) {
                curZoomValue = 0;
            } else if (curZoomValue > params.getMaxZoom()) {
                curZoomValue = params.getMaxZoom();
            }

            if (!params.isSmoothZoomSupported()) {
                params.setZoom(curZoomValue);
                cameraInst.setParameters(params);
                return;
            } else {
                cameraInst.startSmoothZoom(curZoomValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //定点对焦的代码
    private void pointFocus(int x, int y) {
        cameraInst.cancelAutoFocus();
        parameters = cameraInst.getParameters();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            showPoint(x, y);
        }
        cameraInst.setParameters(parameters);
        autoFocus();
    }

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    private void showPoint(int x, int y) {
        if (parameters.getMaxNumMeteringAreas() > 0) {
            List<Camera.Area> areas = new ArrayList<Camera.Area>();
            //xy变换了
            int rectY = -x * 2000 / MyApplication.getApp().getScreenWidth() + 1000;
            int rectX = y * 2000 / MyApplication.getApp().getScreenHeight() - 1000;

            int left = rectX < -900 ? -1000 : rectX - 100;
            int top = rectY < -900 ? -1000 : rectY - 100;
            int right = rectX > 900 ? 1000 : rectX + 100;
            int bottom = rectY > 900 ? 1000 : rectY + 100;
            Rect area1 = new Rect(left, top, right, bottom);
            areas.add(new Camera.Area(area1, 800));
            parameters.setMeteringAreas(areas);
        }

        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ButterKnife.unbind(this);
    }

    private final class MyPictureCallback implements Camera.PictureCallback {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            bundle = new Bundle();
            //将图片字节数据保存在bundle当中,实现数据交换
            bundle.putByteArray("bytes", data);
            new SavePicTask(data).execute();
            // 拍完照后,重新开始预览
            camera.startPreview();
        }
    }

    /**
     * 异步线程更新图片
     */
    private class SavePicTask extends AsyncTask<Void, Void, String> {
        private byte[] data;

        protected void onPreExecute() {
            Log.d(TAG, "onPreExecute: ------------处理中------------");
        }

        //拍摄完成后的照片
        SavePicTask(byte[] data) {
            this.data = data;
        }

        @Override
        protected String doInBackground(Void... params) {
            try {
                return saveToSDCard(data);
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            if (StringUtils.isNotEmpty(result)) {
            } else {
                Toast.makeText(getActivity(), "拍照失败,请稍后重试!", Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * SurfaceCallback
     */
    private final class SurfaceCallback implements SurfaceHolder.Callback {

        public void surfaceDestroyed(SurfaceHolder holder) {
            try {
                if (cameraInst != null) {
                    //停止预览
                    cameraInst.stopPreview();
                    cameraInst.release();
                    cameraInst = null;
                }
            } catch (Exception e) {
                //相机已经关了
            }

        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            if (null == cameraInst) {
                try {
                    cameraInst = Camera.open();
                    cameraInst.setPreviewDisplay(holder);
                    initCamera();
                    cameraInst.startPreview();
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        }
        //屏幕发生变化时进行调用
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            autoFocus();
        }
    }

    //实现自动对焦
    private void autoFocus() {
        new Thread() {
            @Override
            public void run() {
                try {
                    sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (cameraInst == null) {
                    return;
                }
                cameraInst.autoFocus(new Camera.AutoFocusCallback() {
                    @Override
                    public void onAutoFocus(boolean success, Camera camera) {
                        if (success) {
                            //实现相机的参数初始化
                            initCamera();
                        }
                    }
                });
            }
        };
    }

    /**
     * 获取相机的预览尺寸
     */
    private Camera.Size adapterSize = null;
    private Camera.Size previewSize = null;

    private void initCamera() {
        parameters = cameraInst.getParameters();
        parameters.setPictureFormat(PixelFormat.JPEG);
        //if (adapterSize == null) {
        setUpPicSize(parameters);
        setUpPreviewSize(parameters);
        //}
        if (adapterSize != null) {
            parameters.setPictureSize(previewSize.width, previewSize.height);
        }
        //设置比例尺寸
        if (previewSize != null) {
            parameters.setPreviewSize(previewSize.width, previewSize.height);
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            //1连续对焦
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        } else {
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        }
        setDispaly(parameters, cameraInst);
        try {
            cameraInst.setParameters(parameters);
        } catch (Exception e) {
            e.printStackTrace();
        }
        cameraInst.startPreview();
        // 2如果要实现连续的自动对焦,这一句必须加上
        cameraInst.cancelAutoFocus();
    }

    private void setUpPicSize(Camera.Parameters parameters) {
        if (adapterSize != null) {
            return;
        } else {
            adapterSize = findBestPictureResolution();
            return;
        }
    }

    private void setUpPreviewSize(Camera.Parameters parameters) {
        if (previewSize != null) {
            return;
        } else {
            previewSize = findBestPreviewResolution();
        }
    }

    /**
     * 最小预览界面的分辨率
     */
    private static final int MIN_PREVIEW_PIXELS = 480 * 320;
    /**
     * 最大宽高比差
     */
    private static final double MAX_ASPECT_DISTORTION = 0.15;
    private static final String TAG = "Camera";

    /**
     * 找出最适合的预览界面分辨率
     */
    private Camera.Size findBestPreviewResolution() {
        Camera.Parameters cameraParameters = cameraInst.getParameters();
        Camera.Size defaultPreviewResolution = cameraParameters.getPreviewSize();
        List<Camera.Size> rawSupportedSizes = cameraParameters.getSupportedPreviewSizes();
        if (rawSupportedSizes == null) {
            return defaultPreviewResolution;
        }
        // 按照分辨率从大到小排序
        List<Camera.Size> supportedPreviewResolutions = new ArrayList<Camera.Size>(rawSupportedSizes);
        Collections.sort(supportedPreviewResolutions, new Comparator<Camera.Size>() {
            @Override
            public int compare(Camera.Size a, Camera.Size b) {
                int aPixels = a.height * a.width;
                int bPixels = b.height * b.width;
                if (bPixels < aPixels) {
                    return -1;
                }
                if (bPixels > aPixels) {
                    return 1;
                }
                return 0;
            }
        });
        StringBuilder previewResolutionSb = new StringBuilder();
        for (Camera.Size supportedPreviewResolution : supportedPreviewResolutions) {
            previewResolutionSb.append(supportedPreviewResolution.width).append('x').append(supportedPreviewResolution.height).append(' ');
        }
        Log.v(TAG, "Supported preview resolutions: " + previewResolutionSb);
        // 移除不符合条件的分辨率
        double screenAspectRatio = (double) MyApplication.getApp().getScreenWidth() / (double) MyApplication.getApp().getScreenHeight();
        Iterator<Camera.Size> it = supportedPreviewResolutions.iterator();
        while (it.hasNext()) {
            Camera.Size supportedPreviewResolution = it.next();
            int width = supportedPreviewResolution.width;
            int height = supportedPreviewResolution.height;

            // 移除低于下限的分辨率,尽可能取高分辨率
            if (width * height < MIN_PREVIEW_PIXELS) {
                it.remove();
                continue;
            }
            // 在camera分辨率与屏幕分辨率宽高比不相等的情况下,找出差距最小的一组分辨率
            // 由于camera的分辨率是width>height,我们设置的portrait模式中,width<height
            // 因此这里要先交换然preview宽高比后在比较
            boolean isCandidatePortrait = width > height;
            int maybeFlippedWidth = isCandidatePortrait ? height : width;
            int maybeFlippedHeight = isCandidatePortrait ? width : height;
            double aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;
            double distortion = Math.abs(aspectRatio - screenAspectRatio);
            if (distortion > MAX_ASPECT_DISTORTION) {
                it.remove();
                continue;
            }
            // 找到与屏幕分辨率完全匹配的预览界面分辨率直接返回
            if (maybeFlippedWidth == MyApplication.getApp().getScreenWidth() && maybeFlippedHeight == MyApplication.getApp().getScreenHeight()) {
                return supportedPreviewResolution;
            }
        }
        // 如果没有找到合适的,并且还有候选的像素,则设置其中最大比例的,对于配置比较低的机器不太合适
        if (!supportedPreviewResolutions.isEmpty()) {
            Camera.Size largestPreview = supportedPreviewResolutions.get(0);
            return largestPreview;
        }
        // 没有找到合适的,就返回默认的
        return defaultPreviewResolution;
    }

    private Camera.Size findBestPictureResolution() {
        Camera.Parameters cameraParameters = cameraInst.getParameters();
        // 至少会返回一个值
        List<Camera.Size> supportedPicResolutions = cameraParameters.getSupportedPictureSizes();
        StringBuilder picResolutionSb = new StringBuilder();
        for (Camera.Size supportedPicResolution : supportedPicResolutions) {
            picResolutionSb.append(supportedPicResolution.width).append('x')
                    .append(supportedPicResolution.height).append(" ");
        }
        Log.d(TAG, "Supported picture resolutions: " + picResolutionSb);
        Camera.Size defaultPictureResolution = cameraParameters.getPictureSize();
        Log.d(TAG, "default picture resolution " + defaultPictureResolution.width + "x" + defaultPictureResolution.height);
        // 排序
        List<Camera.Size> sortedSupportedPicResolutions = new ArrayList<Camera.Size>(supportedPicResolutions);
        Collections.sort(sortedSupportedPicResolutions, new Comparator<Camera.Size>() {
            @Override
            public int compare(Camera.Size a, Camera.Size b) {
                int aPixels = a.height * a.width;
                int bPixels = b.height * b.width;
                if (bPixels < aPixels) {
                    return -1;
                }
                if (bPixels > aPixels) {
                    return 1;
                }
                return 0;
            }
        });
        // 移除不符合条件的分辨率
        double screenAspectRatio = (double) MyApplication.getApp().getScreenWidth() / (double) MyApplication.getApp().getScreenHeight();
        Iterator<Camera.Size> it = sortedSupportedPicResolutions.iterator();
        while (it.hasNext()) {
            Camera.Size supportedPreviewResolution = it.next();
            int width = supportedPreviewResolution.width;
            int height = supportedPreviewResolution.height;

            // 在camera分辨率与屏幕分辨率宽高比不相等的情况下,找出差距最小的一组分辨率
            // 由于camera的分辨率是width>height,我们设置的portrait模式中,width<height
            // 因此这里要先交换然后在比较宽高比
            boolean isCandidatePortrait = width > height;
            int maybeFlippedWidth = isCandidatePortrait ? height : width;
            int maybeFlippedHeight = isCandidatePortrait ? width : height;
            double aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;
            double distortion = Math.abs(aspectRatio - screenAspectRatio);
            if (distortion > MAX_ASPECT_DISTORTION) {
                it.remove();
                continue;
            }
        }
        // 如果没有找到合适的,并且还有候选的像素,对于照片,则取其中最大比例的,而不是选择与屏幕分辨率相同的
        if (!sortedSupportedPicResolutions.isEmpty()) {
            return sortedSupportedPicResolutions.get(0);
        }
        // 没有找到合适的,就返回默认的
        return defaultPictureResolution;
    }

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

    //实现的图像的正确显示
    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", "图像出错");
        }
    }

    /**
     * 将拍下来的照片存放在SD卡中
     *
     * @param data
     * @throws IOException
     */
    public String saveToSDCard(byte[] data) throws IOException {
        Bitmap croppedImage;
        //获得图片大小
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(data, 0, data.length, options);
        PHOTO_SIZE = options.outHeight > options.outWidth ? options.outWidth : options.outHeight;
        int height = options.outHeight > options.outWidth ? options.outHeight : options.outWidth;
        options.inJustDecodeBounds = false;
        Rect r;
        if (mCurrentCameraId == 1) {
            r = new Rect(height - PHOTO_SIZE, 0, height, PHOTO_SIZE);
        } else {
            r = new Rect(0, 0, PHOTO_SIZE, PHOTO_SIZE);
        }
        try {
            croppedImage = decodeRegionCrop(data, r);
        } catch (Exception e) {
            return null;
        }
        //照片存放的路径
        String imagePath = ImageUtils.saveToFile(FileUtils.getInst().getSystemPhotoPath(), true, croppedImage);
        croppedImage.recycle();
        //拍好的照片带入到CircleCameraStickerActivity
        Intent intent = new Intent(getActivity(), CircleCameraStickerActivity.class);
        intent.putExtra("photoImage", imagePath);
        startActivity(intent);
        return imagePath;
    }

    private Bitmap decodeRegionCrop(byte[] data, Rect rect) {
        InputStream is = null;
        System.gc();
        Bitmap croppedImage = null;
        try {
            is = new ByteArrayInputStream(data);
            BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);

            try {
                croppedImage = decoder.decodeRegion(rect, new BitmapFactory.Options());
            } catch (IllegalArgumentException e) {
            }
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            IOUtil.closeStream(is);
        }
        Matrix m = new Matrix();
        m.setRotate(90, PHOTO_SIZE / 2, PHOTO_SIZE / 2);
        if (mCurrentCameraId == 1) {
            m.postScale(1, -1);
        }
        Bitmap rotatedImage = Bitmap.createBitmap(croppedImage, 0, 0, PHOTO_SIZE, PHOTO_SIZE, m, true);
        if (rotatedImage != croppedImage)
            croppedImage.recycle();
        return rotatedImage;
    }

    /**
     * 闪光灯开关   开->关->自动
     *
     * @param mCamera
     */
    private void turnLight(Camera mCamera) {
        if (mCamera == null || mCamera.getParameters() == null
                || mCamera.getParameters().getSupportedFlashModes() == null) {
            return;
        }
        Camera.Parameters parameters = mCamera.getParameters();
        String flashMode = mCamera.getParameters().getFlashMode();
        List<String> supportedModes = mCamera.getParameters().getSupportedFlashModes();
        if (Camera.Parameters.FLASH_MODE_OFF.equals(flashMode)
                && supportedModes.contains(Camera.Parameters.FLASH_MODE_ON)) {//关闭状态
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
            mCamera.setParameters(parameters);
            iv_flash_lamp.setImageResource(R.mipmap.mgx_camera_open_flash_lamp);
        } else if (Camera.Parameters.FLASH_MODE_ON.equals(flashMode)) {//开启状态
            if (supportedModes.contains(Camera.Parameters.FLASH_MODE_AUTO)) {
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
                iv_flash_lamp.setImageResource(R.mipmap.mgx_camera_auto_flash_lamp);
                mCamera.setParameters(parameters);
            } else if (supportedModes.contains(Camera.Parameters.FLASH_MODE_OFF)) {
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                iv_flash_lamp.setImageResource(R.mipmap.mgx_camera_close_flash_lamp);
                mCamera.setParameters(parameters);
            }
        } else if (Camera.Parameters.FLASH_MODE_AUTO.equals(flashMode)
                && supportedModes.contains(Camera.Parameters.FLASH_MODE_OFF)) {
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            mCamera.setParameters(parameters);
            iv_flash_lamp.setImageResource(R.mipmap.mgx_camera_close_flash_lamp);
        }
    }

    //切换前后置摄像头
    private void switchCamera() {
        mCurrentCameraId = (mCurrentCameraId + 1) % mCameraHelper.getNumberOfCameras();
        releaseCamera();
        Log.d("DDDD", "DDDD----mCurrentCameraId" + mCurrentCameraId);
        setUpCamera(mCurrentCameraId);
    }

    /**
     * 释放摄像头
     */
    public void releaseCamera() {
        if (cameraInst != null) {
            //停止预览
            cameraInst.stopPreview();
            cameraInst.release();
            surfaceHolder.removeCallback(surfaceCallback);
            cameraInst = null;
        }
    }

    /**
     * 开始预览
     */
    public void tartPreview() {
        if (null == cameraInst) {
            try {
                cameraInst = Camera.open();
                cameraInst.setPreviewDisplay(sfv_show_frame.getHolder());
                initCamera();
                cameraInst.startPreview();
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @param mCurrentCameraId2
     */
    private void setUpCamera(int mCurrentCameraId2) {
        cameraInst = getCameraInstance(mCurrentCameraId2);
        if (cameraInst != null) {
            try {
                cameraInst.setPreviewDisplay(sfv_show_frame.getHolder());
                initCamera();
                cameraInst.startPreview();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Log.d(TAG, "setUpCamera: -------切换失败,请重试!---------");

        }
    }

    /**
     * 获取摄像头的id
     *
     * @param id
     * @return
     */
    private Camera getCameraInstance(final int id) {
        Camera c = null;
        try {
            c = mCameraHelper.openCamera(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return c;
    }
}
package com.wj.shoes.shortvideo.utils.camera;

import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.view.Surface;

import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.GINGERBREAD;

/**
 * Created by A-23 on 2018/6/9.
 */
public class CameraHelper {
    private final CameraHelperImpl mImpl;

    public CameraHelper(final Context context) {
        if (SDK_INT >= GINGERBREAD) {
            mImpl = new CameraHelperGB();
        } else {
            mImpl = new CameraHelperBase(context);
        }
    }

    public interface CameraHelperImpl {
        int getNumberOfCameras();

        Camera openCamera(int id);

        Camera openDefaultCamera();

        Camera openCameraFacing(int facing);

        boolean hasCamera(int cameraFacingFront);

        void getCameraInfo(int cameraId, CameraInfo2 cameraInfo);
    }

    public int getNumberOfCameras() {
        return mImpl.getNumberOfCameras();
    }

    public Camera openCamera(final int id) {
        return mImpl.openCamera(id);
    }

    public Camera openDefaultCamera() {
        return mImpl.openDefaultCamera();
    }

    public Camera openFrontCamera() {
        return mImpl.openCameraFacing(Camera.CameraInfo.CAMERA_FACING_FRONT);
    }

    public Camera openBackCamera() {
        return mImpl.openCameraFacing(Camera.CameraInfo.CAMERA_FACING_BACK);
    }

    public boolean hasFrontCamera() {
        return mImpl.hasCamera(Camera.CameraInfo.CAMERA_FACING_FRONT);
    }

    public boolean hasBackCamera() {
        return mImpl.hasCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
    }

    public void getCameraInfo(final int cameraId, final CameraInfo2 cameraInfo) {
        mImpl.getCameraInfo(cameraId, cameraInfo);
    }

    public void setCameraDisplayOrientation(final Activity activity, final int cameraId,
                                            final Camera camera) {
        int result = getCameraDisplayOrientation(activity, cameraId);
        camera.setDisplayOrientation(result);
    }

    public int getCameraDisplayOrientation(final Activity activity, final int cameraId) {
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        int degrees = 0;
        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;
        }

        int result;
        CameraInfo2 info = new CameraInfo2();
        getCameraInfo(cameraId, info);
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
        } else { // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        return result;
    }

    public static class CameraInfo2 {
        public int facing;
        public int orientation;
    }
}

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android Camera2拍照流程如下: 1. 创建CameraManager对象,获取可用的相机列表。 2. 选择一个相机,打开相机设备,创建CameraDevice对象。 3. 创建CaptureSession,设置预览Surface和拍照Surface。 4. 创建CaptureRequest.Builder,设置拍照参数。 5. 调用CaptureSession.capture()方法,开始拍照。 6. 在CaptureSession.CaptureCallback中监听拍照结果,获取拍照的图片数据。 7. 关闭相机设备,释放资源。 以上是Android Camera2拍照的基本流程,具体实现需要根据实际需求进行调整。 ### 回答2: Android camera2拍照流程是由一系列的API方法构成的,主要包括初始化相机,设置CaptureRequest和CaptureSession,以及触发拍照,捕获图像的过程。 首先需要初始化相机,可以通过CameraManager API来实现。在初始化时,需要指定所要使用的相机ID,以及设置相机状态监听器。一旦相机初始化完成,可以通过相机管理器对象获取相机的特性信息,并根据需要设置相机的参数,如预览尺寸、图片格式等。 接下来需要创建CaptureRequest对象,用于设置拍照的相关参数,如拍摄模式、闪光灯、曝光时间等。可以通过CameraDevice API创建CaptureRequest对象,并进行相关设置。 然后需要创建CaptureSession对象,用于处理相机图像的捕获和处理。可以使用CameraDevice的createCaptureSession方法创建CaptureSession,并将所有需要完成的CaptureRequest集合成一个List,然后将其作为参数传递给CaptureSession。 一旦CaptureSession成功创建,可以将CaptureRequest对象发送到CaptureSession,以便开始拍照和捕获图像。可以使用CaptureSession的capture方法来启动图像捕获,并设置捕获回调处理来处理捕获的图像。 最后,对于处理捕获的图像,可以使用ImageReader API将Image对象转换为Bitmap等图像格式,并保存到本地存储设备。可以在ImageReader注册的回调函数中处理Image对象,并将结果保存到本地存储设备。 总之,Android camera2拍照的过程中需要进行初始化相机,设置CaptureRequest和CaptureSession,以及触发拍照,捕获图像等一系列步骤。这些API方法的使用可以实现各种必要的设置和操作,从而使得Android camera2相机拍照流程更为灵活、高效和自由。 ### 回答3: Android camera2是及其完善的相机API,相比于旧版camera API,camera2的API设计更加友好。但是camera2的拍照流程相比于旧版API来说是更加复杂的。因此,本文将详细介绍Android camera2拍照流程。 1. 获取CameraManager实例 CameraManager用于枚举可用相机设备和打开指定的相机设备。 2. 获取CameraCharacteristics实例 在相机设备被打开前,需要获取相机设备的特性信息,例如: 它属于前置摄像头或后置摄像头、支持的预览尺寸、支持的拍照尺寸等。 3. 打开相机设备 使用CameraManager打开指定的相机设备,然后获取相机设备的实例。 4. 创建CaptureSession CaptureSession代表了一个相机拍摄的会话,可以定义预览和拍照的参数设置。 5. 配置CaptureRequest 在CameraDevice创建完成,并且CaptureSession已经准备好之后,开始配置CaptureRequest。CaptureRequest代表了拍照请求参数,需要在此设置各种请求参数,例如:曝光时间、ISO、自动对焦等。 6. 设置CaptureRequest 将CaptureRequest添加到CaptureSession中,开始设置请求参数和相机设备的状态。 7. 开始拍照 当上述流程都完成后,就可以触发拍照了。一般情况下,设置好CaptureRequest之后调用CaptureSession的capture方法即可拍照。 8. 获取照片数据 在照片拍摄完成后,可以通过ImageSaver保存jpg格式的照片。 总结: 相比于旧版的API,Android camera2提供了更多的接口和更强大的能力。在使用camera2时,需要依次执行上述步骤。 此外,值得注意的是,在拍摄完成后,记得要及时释放相关资源,关闭相机设备、关闭CaptureSession、关闭ImageReader等,以免引起性能和内存问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值