说明:
1、点击Camera 应用后,进入CameraActivity.java,完成初始化,包括判断是哪种模式(拍照,摄像,全景拍照)。我们这里说的是拍照模式。
判断此模式是在CameraActivity.java的onCreate 方法里,调用setModuleFromIndex 方法,通过下面语句赋值 mCurrentModule = new PhotoModule();
其中mCurrentModule 是private CameraModule mCurrentModule;
关于CameraModule参考后面章节。
2、进入CameraActivity.java 的 onResume方法,执行下面语句
mCurrentModule.onResumeAfterSuper();
在onResumeAfterSuper 方法里调用prepareCamera方法,来打开Camera,语句如下:
mCameraDevice = CameraUtil.openCamera(
mActivity, mCameraId, mHandler,
mActivity.getCameraOpenErrorCallback());
其中mCameraDevice是com.android.camera.CameraManager.CameraProxy;的实例。
CameraUtil 属于公共的API,用于给不同模块提供对Camera的不同操作。
在它openCamera 方法里,执行下面语句:
CameraHolder.instance().open(handler, cameraId, cb);
其中CameraHolder,典型的单例模式。目的就是控制,相机开启的只有能是一个。再次开启前,要确认上次已经销毁。
3、在CameraHolder 的open 方法里,执行语句
mCameraDevice = CameraManagerFactory
.getAndroidCameraManager().cameraOpen(handler, cameraId, cb);
CameraManagerFactory 调用的工厂模式,创建一个AndroidCameraManagerImpl 实例。并调用它的cameraOpen方法。
AndroidCameraManagerImpl.java 是CameraManager 接口的实现。目的就是对Camera 进行管理。通过与
frameworks/base/core/java/android/hardware/Camera.java 交互,实现软件控制硬件Camera的功能。
在cameraOpen方法中执行
mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0,
CameraOpenErrorCallbackForward.getNewInstance(
handler, callback)).sendToTarget();.
其中mCameraHandler 继承Handler 重写了handleMessage 方法。其中语句
case OPEN_CAMERA:
mCamera = android.hardware.Camera.open(msg.arg1);
return;
就是通过frameworks的Camera.java 类,来调用Camera 驱动层,来开Camera设备的。
4、设备开启后,调用在prepareCamera方法里,调用startPreview();在这里获取SurfaceTexture 的实例。第一次进入,获取的是空,那是因为没有调用PhotoUI的onSurfaceTextureAvailable的方法。这个方法是底层直接调用。在这个方法里语句
mController.onPreviewUIReady();
其中mController 属于PhotoController接口的实例,而PhotoModule 实现了它的方法。在初始化的时候,赋值给它。因此直接调用的是PhotoModule的onPreviewUIReady 方法。在这个方法里,重新调用startPreview();然后获取的SurfaceTexture的实例。通过 mCameraDevice.setPreviewTexture(st);方法,讲设备获取的图像,呈现在手机屏幕。
注意:在AndroidManifest.xml 中添加Camera 权限。
<uses-permission android:name="android.permission.CAMERA" />
5、取景遇到的问题的
当我们取景后,发现获取的图像在屏幕上旋转90度。如何让取景跟屏幕保持一致?
CameraActivity 类中重写onConfigurationChanged 方法。
CameraModule 接口中,增加onConfigurationChanged 方法声明,并且在PhotoModule类中实现。调用PhotoModule 中setDisplayOrientation方法。在setDisplayOrientation方法中调用CameraUtil类中的getDisplayRotation和getDisplayOrientation方法,获取了屏幕与取景需要的方向。
通过mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation); 来设置Camera 设备的显示角度。
6、关闭相机
当我们关闭相机的时候,调用CameraActivity的onPause 方法,然后调用PhotoModule的onPauseAfterSuper方法。在这个方法里stopPreview(); 方法和closeCamera();方法。其中stopPreview(); 是停止设备Camera;closeCamera();是release 设备Camera。一定要release ,否则再次进入Camera 会报错。