Android surfaceview 自定義相機 拍照(閃光燈、前後攝像頭)

在我們app中經常會調用相機進行拍照,然後把拍下來的圖片保存在本地,再上傳到服務端,網上有不少自定義的相機,也下載了不少,但是效果還是不滿意,所以決定自定義下,不多說了,直接上代碼:
public class CameraViews extends SurfaceView implements SurfaceHolder.Callback{
private String TAG=Camera.class.getName();
private Activity mActivity=null;
private Camera camera=null;
private SurfaceHolder holder=null;
/* 是否打開前置相機,true爲前置,false爲後置 */
private boolean mIsFrontCamera=false;
/是否開啓閃光燈 默認關閉閃光燈/
private String isOpenFlashMode= Camera.Parameters.FLASH_MODE_OFF;
private int curRotation=0;
private CameraCallback mCallback=null;

public CameraViews(Context context){
    super(context);
    initSurface();
}

public CameraViews(Context context, AttributeSet attrs) {
    super(context, attrs);
    initSurface();
}

public void setCurActivity(Activity activity){
    this.mActivity=activity;
}

/**
 * @Description:  初始化surface
 * @Since:2015-8-11  
 * @Version:1.1.0
 */
private void initSurface(){
    holder =getHolder();//獲得句柄
    holder.addCallback(this);//添加回調
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//surfaceview不維護自己的緩衝區,等待屏幕渲染引擎將內容推送到用戶面前
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    try {
        if(camera==null){
            openCamera();
        }
        initCameraParams(mActivity);
        camera.setPreviewDisplay(getHolder());
        camera.startPreview();
    } catch (Exception e) {
        Toast.makeText(getContext(), "打開相機失敗", Toast.LENGTH_SHORT).show();
        Log.e(TAG,e.getMessage());
    }
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
//try{
    //camera.stopPreview();
    //攝像頭畫面顯示在Surface上
    //camera.setPreviewDisplay(holder);
    //initCameraParams(mActivity);
    //camera.startPreview();   
//}catch(IOException e) {
    // if (camera != null) camera.release();
    //camera = null;
//}

    //注意:這裏不能進行重新初始化相機,然後在預覽,不然進行橫縱拍照,照出來的圖片旋轉的角度會對應不上,所以這裏直接開啓預覽就好
    camera.startPreview();   
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    camera.stopPreview();
    camera.release();
    camera=null;
    holder=null;

}

@SuppressWarnings("unused")
private PictureCallback pictureCallback=new PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        saveCameraImage(data, camera);
        //這句話也很重要,是將你拍照成功後,圖片可以在相冊中查看到。(只不過我把這句話封裝到保存圖片中,保存圖片順帶加載到相冊)。
        //MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");
        //重新打開預覽圖,進行下一次的拍照準備
        camera.startPreview();
    }
};
/**
 * @Description:設置相機預覽 
 * @Since:2015-8-11  
 * @Version:1.1.0  
 * @param activity
 **/
public void setCameraPreView(){
    if(camera!=null){
        camera.stopPreview();
        initCameraParams(mActivity);
        try {
            camera.setPreviewDisplay(getHolder());
            camera.startPreview();
        } catch (IOException e) {
            Log.e(">>>>>","相機轉換失敗!"+e.getMessage());
        }
    }else{
        Log.e(">>>>>","相機初始化失敗!");
    }
}

/**
 * @Description:保存拍照的圖片
 * @Since:2015-8-11  
 * @Version:1.1.0  
 * @param data
 * @param camera
 */
private void saveCameraImage(byte[] data, Camera camera) {
    if(data==null){
        Log.e(TAG, "獲取圖片流失敗,拍照失敗,請重試!");
        return;
    }
    if(isFrontCamera()){
        if(curRotation==90){
            curRotation=270;
        }else if(curRotation==270){
            curRotation=90;
        }
    }
    Bitmap thumbBM=null;
    thumbBM=BitmapUtils.getInstance().save(mActivity,data,curRotation);
    mCallback.onCameraCallback(thumbBM);
    thumbBM=null;

}

/**
 * @Description:設置相機參數
 * @Since:2015-8-11  
 * @Version:1.1.0
 */
public void initCameraParams(Activity activity){
    Camera.Parameters parameters = camera.getParameters();
    // 選擇合適的預覽尺寸   
    List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
    if (sizeList.size()>0) {
        Size cameraSize=sizeList.get(0);
        //預覽圖片大小
        parameters.setPreviewSize(cameraSize.width, cameraSize.height);
    }

    //設置生成的圖片大小
    sizeList = parameters.getSupportedPictureSizes();
    if (sizeList.size()>0) {
        Size cameraSize=sizeList.get(0);
        for (Size size : sizeList) {
            //小於100W像素
            if (size.width*size.height<100*10000) {
                cameraSize=size;
                break;
            }
        }
        parameters.setPictureSize(cameraSize.width, cameraSize.height);
    }
    //設置圖片格式
    parameters.setPictureFormat(ImageFormat.JPEG);       
    parameters.setJpegQuality(100);
    parameters.setJpegThumbnailQuality(100);
    //自動聚焦模式
    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
    parameters.setFlashMode(getIsOpenFlashMode());
    //curRotation=getPreviewDegree();
    screenDirectionListener();
    //Log.e(">>>>>","curRotation:"+curRotation);
    //parameters.setRotation(curRotation);//生成的圖片轉90°
    //camera.setDisplayOrientation(curRotation);//預覽轉90°預覽圖片旋轉90°
    //camera.setDisplayOrientation(getPreviewDegree());//預覽旋轉90°
    camera.setDisplayOrientation(90);
    camera.setParameters(parameters);
}
public String getIsOpenFlashMode() {
    return isOpenFlashMode;
}

/**
 * @Description:  設置開啓閃光燈(重新預覽)
 * @Since:2015-8-12  
 * @Version:1.1.0  
 * @param mIsOpenFlashMode
 */
public void setIsOpenFlashMode(boolean mIsOpenFlashMode) {
    if(mIsOpenFlashMode)
        this.isOpenFlashMode = Camera.Parameters.FLASH_MODE_ON;
    else
        this.isOpenFlashMode =  Camera.Parameters.FLASH_MODE_OFF;;
    setCameraPreView();//重新預覽相機
}

/**  
 *   根據當前照相機狀態(前置或後置),打開對應相機
 */
private boolean openCamera()  {
    if (camera != null) {
        camera.stopPreview();
        camera.release();
        camera = null;
    }

    if(mIsFrontCamera){
        Camera.CameraInfo cameraInfo=new CameraInfo();
        for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
            Camera.getCameraInfo(i, cameraInfo);
            if(cameraInfo.facing==Camera.CameraInfo.CAMERA_FACING_FRONT){
                try {
                    camera=Camera.open(i);
                } catch (Exception e) {
                    camera =null;
                    return false;
                }
            }
        }
    }else {
        try {
            camera=Camera.open();
        } catch (Exception e) {
            camera =null;
            return false;
        }
    }
    return true;
}

/**
 * @Description:獲取相機攝像頭個數  
 * @Since:2015-8-11  
 * @Version:1.1.0  
 * @return
 */
public int getCameraCount(){
    return Camera.getNumberOfCameras();//得到攝像頭的個數
}

private boolean isFrontCamera(){
    return mIsFrontCamera;
}

/**
 * @Description:轉換前置和後置照相機
 * @Since:2015-8-11  
 * @Version:1.1.0  
 * @return
 */
public boolean switchCamera(){
    mIsFrontCamera=!mIsFrontCamera;
    openCamera();
    if(camera!=null){
        initCameraParams(mActivity);
        //updateCameraOrientation();
        try {
            camera.setPreviewDisplay(getHolder());
            camera.startPreview();
        } catch (IOException e) {
            Log.e(">>>>>","相機轉換失敗!"+e.getMessage());
        }
    }
    return mIsFrontCamera;
}

/**
 * @Description:  拍照
 * @Since:2015-8-31  
 * @Version:1.1.0  
 * @param mCameraCallback
 */
public void takePhoto(CameraCallback mCameraCallback){
    try {
        initSurface();
        initCameraParams(mActivity);
        camera.takePicture(null, null, pictureCallback);//將拍攝到的照片給自定義的對象
        this.mCallback=mCameraCallback;
    } catch (Exception e) {
        Toast.makeText(mActivity,"初始化相機失敗!",Toast.LENGTH_SHORT).show();
    }
}
public interface CameraCallback{
    void onCameraCallback(Bitmap bitmap);
}
/**
 * @Description:  監聽屏幕的旋轉方向
 * @Since:2015-8-12  
 * @Version:1.1.0
 */
private void screenDirectionListener(){
    OrientationEventListener mOrEventListener =new OrientationEventListener(getContext()) {

        @Override
        public void onOrientationChanged(int rotation) {
            //getScreenDirect();
             if (((rotation >= 0) && (rotation <= 45)) || (rotation >= 315)||((rotation>=135)&&(rotation<=225))){////portrait
             } else if (((rotation > 45) && (rotation < 135))||((rotation>225)&&(rotation<315))) {//landscape
             }
            if (((rotation >= 0) && (rotation <= 45)) || (rotation > 315)){//縱屏向上
                rotation=90;
            }else if ((rotation > 45) && (rotation <= 135))  {//橫屏向右
                rotation=180;
            }
            else if ((rotation > 135) && (rotation <= 225)) {//縱屏向下
                rotation=270;
            } 
            else if((rotation > 225) && (rotation <= 315)) { //橫屏向左
                rotation=0;
            }else {
                rotation=0;
            }
            curRotation=rotation;
        }
    };
    mOrEventListener.enable();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章