【Android Camera1】Camera1初始化销毁流程(七) ——初始化伪代码

//CameraView.java
public int mCameraId = DEFAULT_CAMERA_ID;
 @Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
   super.surfaceChanged(holder, format, w, h);
   tryInit(holder, w, h);
}
public void tryInit(SurfaceHolder holder ,int w, int h){
   if(!checkHasPermission(CAMERA)) {
       uiObserver.onPermissionDeny();
       return false;
   }
   uiObserver.onPermissionGranted();
   mAspectRatio = w / h;
   CameraManager.of().initCamera(holder, mAspectRatio, mCameraId)
}

//CameraManager.java
public static final int MSG_INIT_CAMERA = 0;
public void initCamera(SurfaceHolder holder, float aspectRatio, int cameraId,){
	getCameraHandler()
	.sendMessage(handler.obtainMessage(MSG_INIT_CAMERA, cameraId, aspectRatio));
}

...

public void handleMessage(Message msg){
	switch (msg.what) {
		case MSG_INIT_CAMERA:
			camera.initCamera((SurfaceHolder)msg.obj[0], (float)msg.obj[1],(int)msg.obj[2]);
            break;
        ...
	}
}

//Camera1Impl.java
public void initCamera(SurfaceHolder holder, int cameraId, float aspectRatio){
	this.mHolder = holder;
	this.mCameraId = cameraId;
	this.mAspectRatio = aspectRatio;
	synchronized(lock){
		try{
			if(acquireLock(timeout = 2000)){
				Log.i(TAG, "initCamera超时")
			}
			openCamera(cameraId);
			applyDefaultParameters();
			startPreview();
			releaseLock();
			Log.i(TAG, "initCamera succ")
			retryCount = 0;
		}catch(Exception e){
			releaseLock();
			Log.e(TAG, "initCamera exception info = "+e.getInfo();
			if(retryCount > DEFAULT_RETRY_COUNT){
				getCameraHandler().postDelay(()->{
					retryCount++;
					initCamera(holder, cameraId, aspectRatio);
				},20);
			}
		}
	}
}

public void openCamera(int cameraId){
	int count = 0;
		// @return total number of accessible camera devices, 
		//or 0 if there are no cameras or an error was encountered enumerating them.
	try{
		count = Camera.getNumberOfCameras();
	}catch(Exception e){
		count = -1;
	}
	if(count == 0){
		Toast("清检查设备前后置摄像头")
		//释放锁
		releaseLock();
		return;
	}
	if(count == -1){
		releaseLock();
		if(retryCount> DEFAULT_RETRY_COUNT){
			getCameraHandle().postDelay(()->{
				openCamera(cameraId);
				retryCount++;
			},20);
		}
		return;
	}
	retryCount= 0;
	if(mCamera!=null){
		//releaseCamera释放camera,并set null to mCamera。
		releaseCamera();
	}
	mCamera = Camera.open(cameraId);
	if(mCamera == null){
		Toast("打开摄像头失败");
		releaseLock();
		return;
	}
	mCameraId = cameraId;
	Camera.CameraInfo info = new Camera.CameraInfo();
	try{
		Camera.getCameraInfo(mCameraId,info)
	}catch(Exception e){
		Log.e(TAG,"exception info = "+ e.getInfo());
	}
	
	mCanDisableSound = info.canDisableShutterSound;
	if(mCanDisableSound){
		try {
			// 关闭快门声
	       mCamera.enableShutterSound(false);  
	   	}catch (Exception e){
	    }
	}else{
		//TODO 需要做额外的关闭声音容错处理
	}
}

private void applyDefaultParameters(){
	//1.apply方向
	applyDefaultOrientation();
	//2.apply previewSize
	applyDefaultPreviewSize();
	//3.apply pictureSize
	applyDefaultPictureSize();
	//4.apply focus mode
	applyDefaultFocusMode();
	//5.apply flash mode
	applyDefaultFlashMode();
}
private int applyDefaultOrientation() {
 	int displayOrientation;
 	 //1.问题机型兼容逻辑处理
 	if(CameraCompat.Camera1.isOrientationExcepDevice(Build.Model)){
 	 	displayOrientation = CameraCompat.Camera1.getOrientationForExcepDevices();
 	}else{	
 	//2.逻辑计算
	    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;
	    }

//mOrientation为 CameraInfo里 orientation字段,在openCamera阶段保存为变量即可
	    if (mFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
	        displayOrientation = (mOrientation + degrees) % 360;
	        displayOrientation = (360 - displayOrientation) % 360;  
	        // compensate the mirror
	    } else {  // back-facing
	        displayOrientation = (mOrientation - degrees + 360) % 360;
	    }
	}
    try{
    //3.非致命异常 try-catch
   		camera.setDisplayOrientation(displayOrientation);
    }catch(Exception e){
   		Log.e(TAG, "setDisplayOrientation exception info = "+e.getInfo());
    }
}

public void applyDefaultPreviewSize(){
    if (mShowingPreview) {
        mCamera.stopPreview();
    }
	Camera.Parameters params = null;
	try{
		//mCamera.getParameters();需要try-catch住,不是致命bug
		params = mCamera.getParameters();
	}catch(Exception e){
		...
	}
	if(params == null){
		//不设置 return
		return;
	}
	List<Size> previewSize = null;
	try{
		//可参看源码,内部没有异常try-catch。可能会抛异常,也可能返回为null;
		previewSize = params.getSupportedPreviewSizes();
	}catch(Exception e){
		...
	}
	if(previewSize == null || previewSize.size() == 0){
		return;
	}
	float min = Integer.MAX_VALUE;
	Size selectSize = null;
	for(Size s : previewSize){
		float ar = AspectRatio.cal(s);
		if(ar - mAspectRatio < min){
			selectPreviewSize = s;
			min = Math.min(min,Math.abs(mAspectRatio - ar));
		}
	}
	if(selectPreviewSize == null){
		return;
	}
	try{
		params.setPreviewSize(selectSize.getWidth(),selectSize.getHeight());
	}catch(Exception e){
		...
	}
}

public void applyDefaultPictureSize(){
    if (mShowingPreview) {
        mCamera.stopPreview();
    }
	Camera.Parameters params = null;
	try{
		//mCamera.getParameters();需要try-catch住,不是致命bug
		params = mCamera.getParameters();
	}catch(Exception e){
		...
	}
	if(params == null){
		//不设置 return
		return;
	}
	List<Size> pictureSize = null;
	try{
		//可参看源码,内部没有异常try-catch。可能会抛异常,也可能返回为null;
		pictureSize = params.getSupportedPictureSizes();
	}catch(Exception e){
		...
	}
	if(pictureSize == null || pictureSize.size() == 0){
		return;
	}
	float min = Integer.MAX_VALUE;
	Size selectSize = null;
	for(Size s : pictureSize){
		float ar = AspectRatio.cal(s);
		if(ar - mAspectRatio < min){
			selectPictureSize = s;
			min = Math.min(min,Math.abs(mAspectRatio - ar));
		}
	}
	if(selectPictureSize == null){
		return;
	}
	try{
		params.setPictureSize(selectSize.getWidth(),selectSize.getHeight());
	}catch(Exception e){
		...
	}
}

public boolean applyDefaultFocusMode(){
	if(!isCameraOpened()){
		return false;
	}
	try{
	    final List<String> modes = mCameraParameters.getSupportedFocusModes();
	    if(modes == null || modes.size() == 0){
	    	return false;
	    }
	    if (isCurVideoTab()
	    && modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
	        mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
	    } else if (modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
	        mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
	    }else if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
	        mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
	    } else if (modes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
	        mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
	    } else {
	        mCameraParameters.setFocusMode(modes.get(0));
	    }
	}catch(Exception e){
		...
	}
}

private static final SparseArrayCompat<String> FLASH_MODES = new SparseArrayCompat<>();

static {
    FLASH_MODES.put(Constants.FLASH_OFF, Camera.Parameters.FLASH_MODE_OFF);
    FLASH_MODES.put(Constants.FLASH_ON, Camera.Parameters.FLASH_MODE_ON);
    FLASH_MODES.put(Constants.FLASH_TORCH, Camera.Parameters.FLASH_MODE_TORCH);
    FLASH_MODES.put(Constants.FLASH_AUTO, Camera.Parameters.FLASH_MODE_AUTO);
    FLASH_MODES.put(Constants.FLASH_RED_EYE, Camera.Parameters.FLASH_MODE_RED_EYE);
}

private boolean applyDefaultFlashMode(int flash) {
    if (isCameraOpened()) {
        List<String> modes = mCameraParameters.getSupportedFlashModes();
        String mode = FLASH_MODES.get(flash);
        if (modes != null && modes.contains(mode)) {
            mCameraParameters.setFlashMode(mode);
            mFlash = flash;
            return true;
        }
        String currentMode = FLASH_MODES.get(mFlash);
        if (modes == null || !modes.contains(currentMode)) {
            mCameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            mFlash = Constants.FLASH_OFF;
            return true;
        }
        return false;
    } else {
        mFlash = flash;
        return false;
    }
}

public void startPreview(){
	//这里兜底再做一次权限检查防止无权限出错
	if(CheckHasPermission(CAMERA_PERMISSION)){
		Toast("无相机权限")
		return;
	}
	if(isPreviewing){
		Toast("重复初始化")
		return;
	}
	if(mCamera == null){
		//这里因为openCamera底层是异步的在极端情况下,mCamera会由于时许问题在此位null
		return;
	}
	try{
		//mCamera.startPreview() 经常会抛异常错误信息位startPreview fail. 该异常一部分通常与自动对焦有关系,所以这里try-catch cancelAutoFocus.
		//cancelAutoFocus
		mCamera.cancelAutoFocus();
	}catch(Exception e){
		
	}
	synchronize(Lock){
		if(acquireLock(timeot = 2000)){
			Log.w("timeout");
		}
		mCamera.setPreviewDisplay(mSurfaceHolder);
		//previewCallBack监听回调,通知UI层。
		mCamera.setPreviewCallBack(new PreviewCallback(){
			void onPreviewFrame(byte[] data, Camera camera){
				releaseLock();
				if(isPreviewing) return;
				isPreviewing = true;
				CameraManager.of().onCameraPreviewed();=
			}
		})
		try{
			mCamera.startPreview();
		}catch(Exception e){
			Log.e(TAG, "exp info = "+e.getInfos());
			//重试逻辑
			retryStartPreview();
		}
	}
}

public void releaseCamera(){
	if(mCamera == null) return;
	synchronized(Lock){
		try{
			if(acquireLock(timeout = 2000)){
				Log.e(TAG, "timeout")
			}
			mCamera.stopPreview();
			mCamera.release();
			mCamera = null;
			releaseLock();
		}catch(Exception e){
			...
		}
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值