1. 程式人生 > >Android仿最新微信自定義相機(長按拍攝,輕點拍照)

Android仿最新微信自定義相機(長按拍攝,輕點拍照)

最近在開發即時通訊這個模組的時候使用到了自定義的相機,需求與微信一樣,要求相機能長按和輕點,當時在網上找自定義相機的資源,很少,所以,我在這裡把我的一些開發經驗貼出來,供大家學習。

大致完成的功能如下:

  1. 長按拍攝視訊,輕點拍照
  2. 前後攝像頭的切換
  3. 閃光的的開啟,關閉,自動
  4. 圖片的壓縮
  5. 自動聚焦,手動聚焦

效果圖如下:
這裡寫圖片描述

相關程式碼如下:

package com.ses.im.app.chat.newcamera;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import
android.graphics.PointF; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.Surface; import android.view.TextureView; import android.view.View; import
android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import com.ses.im.app.chat.R; import java.io.File; import java.util.concurrent.TimeUnit; import rx.Observable; import rx.Subscriber; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import
rx.schedulers.Schedulers; /** * * 拍攝介面 */ public class CameraActivity extends AppCompatActivity implements View.OnClickListener { /** * 獲取相簿 */ public static final int REQUEST_PHOTO = 1; /** * 獲取視訊 */ public static final int REQUEST_VIDEO = 2; /** * 最小錄製時間 */ private static final int MIN_RECORD_TIME = 1 * 1000; /** * 最長錄製時間 */ private static final int MAX_RECORD_TIME = 15 * 1000; /** * 重新整理進度的間隔時間 */ private static final int PLUSH_PROGRESS = 100; private Context mContext; /** * TextureView */ private TextureView mTextureView; /** * 帶手勢識別 */ private CameraView mCameraView; /** * 錄製按鈕 */ private CameraProgressBar mProgressbar; /** * 頂部像機設定 */ private RelativeLayout rl_camera; /** * 關閉,選擇,前後置 */ private ImageView iv_close, iv_facing; private RelativeLayout iv_choice; private RelativeLayout cancel; /** * 閃光 */ private TextView tv_flash; /** * camera manager */ private CameraManager cameraManager; /** * player manager */ private MediaPlayerManager playerManager; /** * true代表視訊錄製,否則拍照 */ private boolean isSupportRecord; /** * 視訊錄製地址 */ private String recorderPath; /** * 圖片地址 */ private String photoPath; /** * 錄製視訊的時間,毫秒 */ private int recordSecond; /** * 獲取照片訂閱, 進度訂閱 */ private Subscription takePhotoSubscription, progressSubscription; /** * 是否正在錄製 */ private boolean isRecording; /** * 是否為點了拍攝狀態(沒有拍照預覽的狀態) */ private boolean isPhotoTakingState; public static void lanuchForPhoto(Activity context) { Intent intent = new Intent(context, CameraActivity.class); context.startActivityForResult(intent, REQUEST_PHOTO); } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mContext = this; setContentView(R.layout.activity_camera); initView(); initDatas(); } private void initView() { mTextureView = (TextureView) findViewById(R.id.mTextureView); mCameraView = (CameraView) findViewById(R.id.mCameraView); mProgressbar = (CameraProgressBar) findViewById(R.id.mProgressbar); rl_camera = (RelativeLayout) findViewById(R.id.rl_camera); iv_close = (ImageView) findViewById(R.id.iv_close); iv_close.setOnClickListener(this); iv_choice = (RelativeLayout) findViewById(R.id.iv_choice); iv_choice.setOnClickListener(this); iv_close.setOnClickListener(this); iv_facing = (ImageView) findViewById(R.id.iv_facing); iv_facing.setOnClickListener(this); iv_close.setOnClickListener(this); tv_flash = (TextView) findViewById(R.id.tv_flash); tv_flash.setOnClickListener(this); cancel= (RelativeLayout) findViewById(R.id.cancel); cancel.setOnClickListener(this); } protected void initDatas() { cameraManager = CameraManager.getInstance(getApplication()); playerManager = MediaPlayerManager.getInstance(getApplication()); cameraManager.setCameraType(isSupportRecord ? 1 : 0); tv_flash.setVisibility(cameraManager.isSupportFlashCamera() ? View.VISIBLE : View.GONE); setCameraFlashState(); iv_facing.setVisibility(cameraManager.isSupportFrontCamera() ? View.VISIBLE : View.GONE); rl_camera.setVisibility(cameraManager.isSupportFlashCamera() || cameraManager.isSupportFrontCamera() ? View.VISIBLE : View.GONE); final int max = MAX_RECORD_TIME / PLUSH_PROGRESS; mProgressbar.setMaxProgress(max); /** * 拍照,拍攝按鈕監聽 */ mProgressbar.setOnProgressTouchListener(new CameraProgressBar.OnProgressTouchListener() { @Override public void onClick(CameraProgressBar progressBar) { cameraManager.takePhoto(callback); isSupportRecord = false; } @Override public void onLongClick(CameraProgressBar progressBar) { isSupportRecord = true; cameraManager.setCameraType(1); rl_camera.setVisibility(View.GONE); recorderPath = FileUtils.getUploadVideoFile(mContext); cameraManager.startMediaRecord1(recorderPath); isRecording = true; progressSubscription = Observable.interval(100, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()).take(max).subscribe(new Subscriber<Long>() { @Override public void onCompleted() { stopRecorder(true); } @Override public void onError(Throwable e) { } @Override public void onNext(Long aLong) { mProgressbar.setProgress(mProgressbar.getProgress() + 1); } }); } @Override public void onZoom(boolean zoom) { cameraManager.handleZoom(zoom); } @Override public void onLongClickUp(CameraProgressBar progressBar) { // isSupportRecord = false; cameraManager.setCameraType(0); stopRecorder(true); if (progressSubscription != null) { progressSubscription.unsubscribe(); } } @Override public void onPointerDown(float rawX, float rawY) { if (mTextureView != null) { mCameraView.setFoucsPoint(new PointF(rawX, rawY)); } } }); /* *點選預覽圖聚焦 */ mCameraView.setOnViewTouchListener(new CameraView.OnViewTouchListener() { @Override public void handleFocus(float x, float y) { cameraManager.handleFocusMetering(x, y); } @Override public void handleZoom(boolean zoom) { cameraManager.handleZoom(zoom); } }); } /** * 設定閃光狀態 */ private void setCameraFlashState() { int flashState = cameraManager.getCameraFlash(); switch (flashState) { case 0: //自動 tv_flash.setSelected(true); tv_flash.setText("自動"); break; case 1://open tv_flash.setSelected(true); tv_flash.setText("開啟"); break; case 2: //close tv_flash.setSelected(false); tv_flash.setText("關閉"); break; } } /** * 是否顯示錄製按鈕 * @param isShow */ private void setTakeButtonShow(boolean isShow) { if (isShow) { mProgressbar.setVisibility(View.VISIBLE); rl_camera.setVisibility(cameraManager.isSupportFlashCamera() || cameraManager.isSupportFrontCamera() ? View.VISIBLE : View.GONE); } else { mProgressbar.setVisibility(View.GONE); rl_camera.setVisibility(View.GONE); } } /** * 停止拍攝 */ private void stopRecorder(boolean play) { isRecording = false; cameraManager.stopMediaRecord(); recordSecond = mProgressbar.getProgress() * PLUSH_PROGRESS;//錄製多少毫秒 mProgressbar.reset(); if (recordSecond < MIN_RECORD_TIME) {//小於最小錄製時間作廢 if (recorderPath != null) { FileUtils.delteFiles(new File(recorderPath)); recorderPath = null; recordSecond = 0; } setTakeButtonShow(true); } else if (play && mTextureView != null && mTextureView.isAvailable()){ setTakeButtonShow(false); mProgressbar.setVisibility(View.GONE); iv_choice.setVisibility(View.VISIBLE); cancel.setVisibility(View.VISIBLE); iv_close.setVisibility(View.GONE); cameraManager.closeCamera(); playerManager.playMedia(new Surface(mTextureView.getSurfaceTexture()), recorderPath); } } @Override protected void onResume() { super.onResume(); if (mTextureView.isAvailable()) { if (recorderPath != null) {//優先播放視訊 iv_choice.setVisibility(View.VISIBLE); setTakeButtonShow(false); playerManager.playMedia(new Surface(mTextureView.getSurfaceTexture()), recorderPath); } else { iv_choice.setVisibility(View.GONE); setTakeButtonShow(true); cameraManager.openCamera(mTextureView.getSurfaceTexture(), mTextureView.getWidth(), mTextureView.getHeight()); } } else { mTextureView.setSurfaceTextureListener(listener); } } @Override protected void onPause() { if (progressSubscription != null) { progressSubscription.unsubscribe(); } if (takePhotoSubscription != null) { takePhotoSubscription.unsubscribe(); } if (isRecording) { stopRecorder(false); } cameraManager.closeCamera(); playerManager.stopMedia(); super.onPause(); } @Override protected void onDestroy() { mCameraView.removeOnZoomListener(); super.onDestroy(); } @Override public void onClick(View v) { int i = v.getId(); if (i == R.id.iv_close) { // if (recorderPath != null) {//有拍攝好的正在播放,重新拍攝 // FileUtils.delteFiles(new File(recorderPath)); // recorderPath = null; // recordSecond = 0; // playerManager.stopMedia(); // setTakeButtonShow(true); // iv_choice.setVisibility(View.GONE); // cameraManager.openCamera(mTextureView.getSurfaceTexture(), mTextureView.getWidth(), mTextureView.getHeight()); // } else if (isPhotoTakingState) { // isPhotoTakingState = false; // iv_choice.setVisibility(View.GONE); // setTakeButtonShow(true); // cameraManager.restartPreview(); // } else { finish(); // } } else if (i == R.id.iv_choice) {//拿到圖片或視訊路徑 Intent intent=new Intent(); if(isSupportRecord){ intent.putExtra("videopath", recorderPath); setResult(3, intent); finish(); }else{ intent.putExtra("videopath", photoPath); setResult(3, intent); finish(); } } else if (i == R.id.tv_flash) { cameraManager.changeCameraFlash(mTextureView.getSurfaceTexture(), mTextureView.getWidth(), mTextureView.getHeight()); setCameraFlashState(); } else if (i == R.id.iv_facing) { cameraManager.changeCameraFacing(mTextureView.getSurfaceTexture(), mTextureView.getWidth(), mTextureView.getHeight()); }else if(i == R.id.cancel){ if (recorderPath != null) {//有拍攝好的正在播放,重新拍攝 FileUtils.delteFiles(new File(recorderPath)); recorderPath = null; recordSecond = 0; playerManager.stopMedia(); setTakeButtonShow(true); iv_choice.setVisibility(View.GONE); cancel.setVisibility(View.GONE); iv_close.setVisibility(View.VISIBLE); cameraManager.openCamera(mTextureView.getSurfaceTexture(), mTextureView.getWidth(), mTextureView.getHeight()); } else if (isPhotoTakingState) { isPhotoTakingState = false; iv_choice.setVisibility(View.GONE); cancel.setVisibility(View.GONE); iv_close.setVisibility(View.VISIBLE); setTakeButtonShow(true); cameraManager.restartPreview(); } } } /** * camera回撥監聽 */ private TextureView.SurfaceTextureListener listener = new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { if (recorderPath != null) { iv_choice.setVisibility(View.VISIBLE); setTakeButtonShow(false); playerManager.playMedia(new Surface(texture), recorderPath); } else { setTakeButtonShow(true); iv_choice.setVisibility(View.GONE); cameraManager.openCamera(texture, width, height); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) { } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { return true; } @Override public void onSurfaceTextureUpdated(SurfaceTexture texture) { } }; private Camera.PictureCallback callback = new Camera.PictureCallback() { @Override public void onPictureTaken(final byte[] data, Camera camera) { setTakeButtonShow(false); takePhotoSubscription = Observable.create(new Observable.OnSubscribe<Boolean>() { @Override public void call(Subscriber<? super Boolean> subscriber) { if (!subscriber.isUnsubscribed()) { photoPath = FileUtils.getUploadPhotoFile(mContext); isPhotoTakingState = FileUtils.savePhoto(photoPath, data, cameraManager.isCameraFrontFacing()); subscriber.onNext(isPhotoTakingState); } } }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Boolean>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(Boolean aBoolean) { if (aBoolean != null && aBoolean) { iv_choice.setVisibility(View.VISIBLE); cancel.setVisibility(View.VISIBLE); iv_close.setVisibility(View.GONE); } else { setTakeButtonShow(true); } } }); } }; }

相機管理類:

package com.ses.im.app.chat.newcamera;

import android.app.Application;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.util.Log;
import android.widget.Toast;

import com.ses.im.app.chat.util.AppConfig;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 
 * 相機管理類
 */

public final class CameraManager {

    private Application context;
    /**
     * camera
     */
    private Camera mCamera;
    private Camera.Parameters mParameters;
    /**
     * 視訊錄製
     */
    private MediaRecorder mMediaRecorder;
    /**
     * 相機閃光狀態
     */
    private int cameraFlash;
    /**
     * 前後置狀態
     */
    private int cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
    /**
     * 是否支援前置攝像,是否支援閃光
     */
    private boolean isSupportFrontCamera, isSupportFlashCamera;
    /**
     * 錄製視訊的相關引數
     */
    private CamcorderProfile mProfile;
    /**
     * 0為拍照, 1為錄影
     */
    private int cameraType;

    private CameraManager(Application context) {
        this.context = context;
        isSupportFrontCamera = CameraUtils.isSupportFrontCamera();
        isSupportFlashCamera = CameraUtils.isSupportFlashCamera(context);
        if (isSupportFrontCamera) {
            cameraFacing = CameraUtils.getCameraFacing(context, Camera.CameraInfo.CAMERA_FACING_BACK);
        }
        if (isSupportFlashCamera) {
            cameraFlash = CameraUtils.getCameraFlash(context);
        }
    }

    private static CameraManager INSTANCE;

    public static CameraManager getInstance(Application context) {
        if (INSTANCE == null) {
            synchronized (CameraManager.class) {
                if (INSTANCE == null) {
                    INSTANCE = new CameraManager(context);
                }
            }
        }
        return INSTANCE;
    }

    /**
     * 開啟camera
     */
    public void openCamera(SurfaceTexture surfaceTexture, int width, int height) {
        if (mCamera == null) {
            mCamera = Camera.open(cameraFacing);//開啟當前選中的攝像頭
            mProfile = CamcorderProfile.get(cameraFacing, CamcorderProfile.QUALITY_HIGH);
            try {
                mCamera.setDisplayOrientation(90);//預設豎直拍照
                mCamera.setPreviewTexture(surfaceTexture);
                initCameraParameters(cameraFacing, width, height);
                mCamera.startPreview();
            } catch (Exception e) {
                LogUtils.i(e);
                if (mCamera != null) {
                    mCamera.release();
                    mCamera = null;
                }
            }
        }
    }

    /**
     * 開啟預覽,前提是camera初始化了
     */
    public void restartPreview() {
        if (mCamera == null) return;
        try {
            Camera.Parameters parameters = mCamera.getParameters();
            int zoom = parameters.getZoom();
            if (zoom > 0) {
                parameters.setZoom(0);
                mCamera.setParameters(parameters);
            }
            mCamera.startPreview();
        } catch (Exception e) {
            LogUtils.i(e);
            if (mCamera != null) {
                mCamera.release();
                mCamera = null;
            }
        }
    }

    private void initCameraParameters(int cameraId, int width, int height) {
        Camera.Parameters parameters = mCamera.getParameters();
        if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            List<String> focusModes = parameters.getSupportedFocusModes();
            if (focusModes != null) {
                if (cameraType == 0) {
                    if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                    }
                } else {
                    if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                    }
                }
            }
        }
        parameters.setRotation(90);//設定旋轉程式碼,
        switch (cameraFlash) {
            case 0:
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
                break;
            case 1:
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                break;
            case 2:
                parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                break;
        }
        List<Camera.Size> pictureSizes = parameters.getSupportedPictureSizes();
        List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
        if (!isEmpty(pictureSizes) && !isEmpty(previewSizes)) {
            /*for (Camera.Size size : pictureSizes) {
                LogUtils.i("pictureSize " + size.width + "  " + size.height);
            }
            for (Camera.Size size : pictureSizes) {
                LogUtils.i("previewSize " + size.width + "  " + size.height);
            }*/
            Camera.Size optimalPicSize = getOptimalCameraSize(pictureSizes, width, height);
            Camera.Size optimalPreSize = getOptimalCameraSize(previewSizes, width, height);
//            Camera.Size optimalPicSize = getOptimalSize(pictureSizes, width, height);
//            Camera.Size optimalPreSize = getOptimalSize(previewSizes, width, height);
            LogUtils.i("TextureSize "+width+" "+height+" optimalSize pic " + optimalPicSize.width + " " + optimalPicSize.height + " pre " + optimalPreSize.width + " " + optimalPreSize.height);
            parameters.setPictureSize(optimalPicSize.width, optimalPicSize.height);
            parameters.setPreviewSize(optimalPreSize.width, optimalPreSize.height);
            mProfile.videoFrameWidth = optimalPreSize.width;
            mProfile.videoFrameHeight = optimalPreSize.height;
            mProfile.videoBitRate = 5000000;//此引數主要決定視訊拍出大小
        }
        mCamera.setParameters(parameters);
    }

    /**
     * 釋放攝像頭
     */
    public void closeCamera() {
        this.cameraType = 0;
        if (mCamera != null) {
            try {
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            } catch (Exception e) {
                LogUtils.i(e);
                if (mCamera != null) {
                    mCamera.release();
                    mCamera = null;
                }
            }
        }
    }

    /**
     * 集合不為空
     *
     * @param list
     * @param <E>
     * @return
     */
    private <E> boolean isEmpty(List<E> list) {
        return list == null || list.isEmpty();
    }

    /**
     *
     * @param sizes 相機support引數
     * @param w
     * @param h
     * @return 最佳Camera size
     */
    private Camera.Size getOptimalCameraSize(List<Camera.Size> sizes, int w, int h){
        sortCameraSize(sizes);
        int position = binarySearch(sizes, w*h);
        return sizes.get(position);
    }

    /**
     *
     * @param sizes
     * @param targetNum 要比較的數
     * @return
     */
    private int binarySearch(List<Camera.Size> sizes,int targetNum){
        int targetIndex;
        int left = 0,right;
        int length = sizes.size();
        for (right = length-1;left != right;){
            int midIndex = (right + left)/2;
            int mid = right - left;
            Camera.Size size = sizes.get(midIndex);
            int midValue = size.width * size.height;
            if (targetNum == midValue){
                return midIndex;
            }
            if (targetNum > midValue){
                left = midIndex;
            }else {
                right = midIndex;
            }

            if (mid <= 1){
                break;
            }
        }
        Camera.Size rightSize = sizes.get(right);
        Camera.Size leftSize = sizes.get(left);
        int rightNum = rightSize.width * rightSize.height;
        int leftNum = leftSize.width * leftSize.height;
        targetIndex = Math.abs((rightNum - leftNum)/2) > Math.abs(rightNum - targetNum) ? right : left;
        return targetIndex;
    }

    /**
     * 排序
     * @param previewSizes
     */
    private void sortCameraSize(List<Camera.Size> previewSizes){
        Collections.sort(previewSizes, new Comparator<Camera.Size>() {
            @Override
            public int compare(Camera.Size size1, Camera.Size size2) {
                int compareHeight = size1.height - size2.height;
                if (compareHeight == 0){
                    return (size1.width == size2.width ? 0 :(size1.width > size2.width ? 1:-1));
                }
                return compareHeight;
            }
        });
    }



    /**
     * 獲取最佳預覽相機Size引數
     *
     * @return
     */
    private Camera.Size getOptimalSize(List<Camera.Size> sizes, int w, int h) {
        Camera.Size optimalSize = null;
        float targetRadio = h / (float) w;
        float optimalDif = Float.MAX_VALUE; //最匹配的比例
        int optimalMaxDif = Integer.MAX_VALUE;//最優的最大值差距
        for (Camera.Size size : sizes) {
            float newOptimal = size.width / (float) size.height;
            float newDiff = Math.abs(newOptimal - targetRadio);
            if (newDiff < optimalDif) { //更好的尺寸
                optimalDif = newDiff;
                optimalSize = size;
                optimalMaxDif = Math.abs(h - size.width);
            } else if (newDiff == optimalDif) {//更好的尺寸
                int newOptimalMaxDif = Math.abs(h - size.width);
                if (newOptimalMaxDif < optimalMaxDif) {
                    optimalDif = newDiff;
                    optimalSize = size;
                    optimalMaxDif = newOptimalMaxDif;
                }
            }
        }
        return optimalSize;
    }

    /**
     * 縮放
     * @param isZoomIn
     */
    public void handleZoom(boolean isZoomIn) {
        if (mCamera == null) return;
        Camera.Parameters params = mCamera.getParameters();
        if (params == null) return;
        if (params.isZoomSupported()) {
            int maxZoom = params.getMaxZoom();
            int zoom = params.getZoom();
            if (isZoomIn && zoom < maxZoom) {
                zoom++;
            } else if (zoom > 0) {
                zoom--;
            }
            params.setZoom(zoom);
            mCamera.setParameters(params);
        } else {
            LogUtils.i("zoom not supported");
        }
    }

    /**
     * 更換前後置攝像
     */
    public void changeCameraFacing(SurfaceTexture surfaceTexture, int width, int height) {
        if(isSupportFrontCamera) {
            Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
            int cameraCount = Camera.getNumberOfCameras();//得到攝像頭的個數
            for(int i = 0; i < cameraCount; i++) {
                Camera.getCameraInfo(i, cameraInfo);//得到每一個攝像頭的資訊
                if(cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) { //現在是後置,變更為前置
                    if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表攝像頭的方位為前置
                        closeCamera();
                        cameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK;
                        CameraUtils.setCameraFacing(context, cameraFacing);
                        openCamera(surfaceTexture, width, height);
                        break;
                    }
                } else {//現在是前置, 變更為後置
                    if(cameraInfo.facing  == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表攝像頭的方位
                        closeCamera();
                        cameraFacing = Camera.CameraInfo.CAMERA_FACING_FRONT;
                        CameraUtils.setCameraFacing(context, cameraFacing);
                        openCamera(surfaceTexture, width, height);
                        break;
                    }
                }
            }
        } else { //不支援攝像機
            Toast.makeText(context, "您的手機不支援前置攝像", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 改變閃光狀態
     */
    public void changeCameraFlash(SurfaceTexture surfaceTexture, int width, int height) {
        if (!isSupportFlashCamera) {
            Toast.makeText(context, "您的手機不支閃光", Toast.LENGTH_SHORT).show();
            return;
        }
        if(mCamera != null) {
            Camera.Parameters parameters = mCamera.getParameters();
            if(parameters != null) {
                int newState = cameraFlash;
                switch (cameraFlash) {
                    case 0: //自動
                        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                        newState = 1;
                        break;
                    case 1://open
                        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                        newState = 2;
                        break;
                    case 2: //close
                        parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
                        newState = 0;
                        break;
                }
                cameraFlash = newState;
                CameraUtils.setCameraFlash(context, newState);
                mCamera.setParameters(parameters);
            }
        }
    }

    /**
     * 拍照
     */
    public void takePhoto(Camera.PictureCallback callback) {
        if (mCamera != null) {
            try {
                mCamera.takePicture(null, null, callback);
            } catch(Exception e) {
                Toast.makeText(context, "拍攝失敗", Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * 開始錄製視訊
     */
//    public void startMediaRecord(String savePath) {
//        if (mCamera == null || mProfile == null) return;
//        mCamera.unlock();
//        if (mMediaRecorder == null) {
//            mMediaRecorder = new MediaRecorder();
//        }
//        if (isCameraFrontFacing()) {
//            mMediaRecorder.setOrientationHint(270);
//            Log.i("wujie","front");
//        }else
//        {
//            Log.i("wujie","back");
//            mMediaRecorder.setOrientationHint(90);
//        }
//        mMediaRecorder.reset();
//        mMediaRecorder.setCamera(mCamera);
//        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
//        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
//        mMediaRecorder.setProfile(mProfile);
//        mMediaRecorder.setOutputFile(savePath);
//        try {
//            mMediaRecorder.prepare();
//            mMediaRecorder.start();
//        } catch (Exception e) {
//            e.printStackTrace();
//
//        }
//    }
    /**
     * 開始錄製視訊
     */
    public void startMediaRecord1(String savePath) {
        if (mCamera == null) {
            return;
        }
        if (mMediaRecorder == null) {
            mMediaRecorder = new MediaRecorder();
        } else {
            mMediaRecorder.reset();
        }


        if (isCameraFrontFacing()) {
            mMediaRecorder.setOrientationHint(270);
            Log.i("wujie","front");
        }else
        {
            Log.i("wujie","back");
            mMediaRecorder.setOrientationHint(90);
        }
        mParameters = mCamera.getParameters();
        mCamera.unlock();
        mMediaRecorder.setCamera(mCamera);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        // 設定錄影引數
        mMediaRecorder.setProfile(CamcorderProfile.get(AppConfig.VIDEOSIZE));
        try {
            mMediaRecorder.setOutputFile(savePath);
            mMediaRecorder.prepare();
            mMediaRecorder.start();
        } catch (Exception e) {

        }

    }

    /**
     * 停止錄製
     */
    public void stopMediaRecord() {
        this.cameraType = 0;
        stopRecorder();
        releaseMediaRecorder();
    }

    private void releaseMediaRecorder() {
        if (mMediaRecorder != null) {
            try {
                mMediaRecorder.reset();
                mMediaRecorder.release();
                mMediaRecorder = null;
                mCamera.lock();
            } catch (Exception e) {
                e.printStackTrace();
                LogUtils.i(e);
            }
        }
    }

    private void stopRecorder() {
        if (mMediaRecorder != null) {
            try {
                mMediaRecorder.stop();
            } catch (Exception e) {
                e.printStackTrace();
                LogUtils.i(e);
            }

        }
    }

    public boolean isSupportFrontCamera() {
        return isSupportFrontCamera;
    }

    public boolean isSupportFlashCamera() {
        return isSupportFlashCamera;
    }

    public boolean isCameraFrontFacing() {
        return cameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT;
    }

    /**
     * 設定對焦型別
     * @param cameraType
     */
    public void setCameraType(int cameraType) {
        this.cameraType = cameraType;
        if (mCamera != null) {//拍攝視訊時
            if (cameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                Camera.Parameters parameters = mCamera.getParameters();
                List<String> focusModes = parameters.getSupportedFocusModes();
                if (focusModes != null) {
                    if (cameraType == 0) {
                        if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
                        }
                    } else {
                        if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
                            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                        }
                    }
                }
            }
        }
    }

    public int getCameraFlash() {
        return cameraFlash;
    }

    /**
     * 對焦
     * @param x
     * @param y
     */
    public void handleFocusMetering(float x, float y) {
        if(mCamera!=null){
            Camera.Parameters params = mCamera.getParameters();
            Camera.Size previewSize = params.getPreviewSize();
            Rect focusRect = calculateTapArea(x, y, 1f, previewSize);
            Rect meteringRect = calculateTapArea(x, y, 1.5f, previewSize);
            mCamera.cancelAutoFocus();

            if (params.getMaxNumFocusAreas() > 0) {
                List<Camera.Area> focusAreas = new ArrayList<>();
                focusAreas.add(new Camera.Area(focusRect, 1000));
                params.setFocusAreas(focusAreas);
            } else {
                LogUtils.i("focus areas not supported");
            }
            if (params.getMaxNumMeteringAreas() > 0) {
                List<Camera.Area> meteringAreas = new ArrayList<>();