【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){
    
    
			...
		}
	}
}

猜你喜欢

转载自blog.csdn.net/Scott_S/article/details/122286810
今日推荐