openCamera 流程
CameraActivity.java
@Override
public void onCreateTasks(Bundle state) {
...
// oncreate manager initialize
CameraFilmstripDataAdapter.THREAD_POOL_EXECUTOR.execute(mOncreateManagerInitialize);
// oncreate - onecameramanager
CameraFilmstripDataAdapter.THREAD_POOL_EXECUTOR.execute(mOncreateOneCameraManager);
// oncreate modules info and set current module
CameraFilmstripDataAdapter.THREAD_POOL_EXECUTOR
.execute(mOncreateModulesInfoAndCurrentModule);
// oncreate - camera controller
CameraFilmstripDataAdapter.THREAD_POOL_EXECUTOR.execute(mOncreateCameraController);
// oncreate - module data setting
CameraFilmstripDataAdapter.THREAD_POOL_EXECUTOR.execute(mOnCreateDataSeting);
// oncreate - request open camera
CameraFilmstripDataAdapter.THREAD_POOL_EXECUTOR.execute(mOncreateOpencamera);
// other task
CameraFilmstripDataAdapter.THREAD_POOL_EXECUTOR
.execute(mOncreateOtherTaskInOncreateProcess);
CameraFilmstripDataAdapter.THREAD_POOL_EXECUTOR.execute(mOncreateOtherTask);
// init module ui
postInit();
...
}
// oncreate - request open camera
private Runnable mOncreateOpencamera = new Runnable() {
@Override
public void run() {
...
mCameraController.requestCamera(
mDataModuleManager.getInstance(CameraActivity.this)
.getTempCameraModule().getInt(Keys.KEY_CAMERA_ID, 0),
mCurrentModule.useNewApi());
...
}
};
CameraController.java
@Override
public void requestCamera(int id, boolean useNewApi) {
...
checkAndOpenCamera(cameraManager, id, mCallbackHandler, this);
...
}
接下来分析 checkAndOpenCamera 流程
checkAndOpenCamera .png最后通知每个 implements ModuleController 的模式,Camera 已经处于可用状态
以 PhotoModule 分析开启预览流程
PhotoModule.java
@Override
public void onCameraAvailable(CameraProxy cameraProxy) {
...
startPreview(true);
...
}
protected void startPreview(boolean optimize) {
...
// update Settings before start preview
if(settingchange){
settingchange = false;
} else {
updateSettingAfterOpencamera(optimize);
}
// 设置预览SurfaceHolder
if (isUseSurfaceView()) {
if (optimize) {
mCameraDevice.setPreviewDisplay(mActivity.getCameraAppUI().getSurfaceHolder());
} else {
mCameraDevice.setPreviewDisplayWithoutOptimize(
mActivity.getCameraAppUI().getSurfaceHolder());
}
} else {
if (optimize) {
mCameraDevice.setPreviewTexture(mActivity.getCameraAppUI().getSurfaceTexture());
} else {
mCameraDevice.setPreviewTextureWithoutOptimize(mActivity.getCameraAppUI()
.getSurfaceTexture());
}
}
...
// 设置预览回调
CameraAgent.CameraStartPreviewCallback startPreviewCallback
= new CameraAgent.CameraStartPreviewCallback() {
@Override
public void onPreviewStarted() {
...
}
};
// 开始预览
doStartPreview(startPreviewCallback, mCameraDevice);
...
}
protected void doStartPreview(CameraAgent.CameraStartPreviewCallback startPreviewCallback,
CameraAgent.CameraProxy cameraDevice) {
// 开始预览
if (useNewApi()) {
mCameraDevice.startPreview();
startPreviewCallback.onPreviewStarted();
} else {
mCameraDevice.startPreviewWithCallback(new Handler(Looper.getMainLooper()),
startPreviewCallback);
}
...
}
拍照流程
PhotoModule.java
@Override
public boolean capture() {
...
// apply Settings
mCameraDevice.applySettings(mCameraSettings);
// Set JPEG orientation. Even if screen UI is locked in portrait, camera
// orientation should
// still match device orientation (e.g., users should always get
// landscape photos while
// capturing by putting device in landscape.)
mCameraDevice.setJpegOrientation(mJpegRotation);
// takePicture start!
mCameraDevice.takePicture(mHandler,
new ShutterCallback(false),
mRawPictureCallback, mPostViewPictureCallback, new JpegPictureCallback(loc));
...
return true;
}
private final class JpegPictureCallback implements CameraPictureCallback {
Location mLocation;
public JpegPictureCallback(Location loc) {
...
}
@Override
public void onPictureTaken(final byte[] originalJpegData,
final CameraProxy camera) {
...
// 播放拍照音
mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
...
// 更新缩略图
startPeekAnimation(originalJpegData);
...
// 如果是三方调用拍照则 stopPreview
if (mIsImageCaptureIntent) {
stopPreview();
}
...
// 重新 startPreview
if (!mIsImageCaptureIntent
&& mContinuousCaptureCount <= 0 && isLastCallback()) {
setupPreview();
}
...
// 保存图片
saveFinalPhoto(originalJpegData, name, exif, camera, burstMode);
...
}
}
Q:为什么 takePicture 后需要重新 startPreview
A:
/**
* <p>This method is only valid when preview is active (after
* {@link #startPreview()}). Preview will be stopped after the image is
* taken; callers must call {@link #startPreview()} again if they want to
* re-start preview or take more pictures. This should not be called between
* {@link android.media.MediaRecorder#start()} and
* {@link android.media.MediaRecorder#stop()}.
*/
public final void takePicture(ShutterCallback shutter, PictureCallback raw,
PictureCallback postview, PictureCallback jpeg) {
}
网友评论