Get清风Android4.4Cameraapp初始化分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Android4.4-Camera-app初始化分析
Android4.4 Camera app初始化分析
Camera app提供的主要功能:预览,拍照,摄影,全景拍摄而这些功能统一组织在CameraActivity这个组件中,并细分到各个模块逐步实现。
其中涉及的类如以下图
CameraUtil Photo Controller Camera Module
+init()
PreferenceGroup
CameraSettings
PhotoModule
-mPreferences
-mUI
-mPreferenceGroup
WideAnglePanoramaModule
VideoModule
CameraActivity
PhotoUI
-mController
ComboPreferences
PhotoMenu OnScreenIndicators
PhotoModule:负责与拍照相关的局部
VideoModule:负责与视频录制相关的局部WideAnglePanoramaModule:全景照片的拍摄
接下来我们分析PhotoModule启动过程,其他两个模块类似。
首先给出时序图,结合时序图,分析每一步的实现
VideoModule
CameraActivity PhotoUI PhotoMenu PreferenceGroup
1 : onCreate()
2 : new PhotoModule()
3 : init()
4 : new PhotoUI()
5 : onResume()
6 : CurrentModule.onResumeAfterSuper()
7 : onResumeTasks()
8 : prepareCamera()
9 : startPreview()
10 : onCameraOpened()
11 : openCameraCommon()
12 : loadCameraPreferences()
13 : settings.getPreferenceGroup()
14 : mUI.onCameraOpened()
15 : new PhotoMenu()
Step1:CameraActivity.onCreate()
当在launcher界面点击camera图标的时候,该函数首先被调用。
public void onCreate(Bundle state) {
…
setContentView(yout.camera_filmstrip);
…
LayoutInflater inflater = getLayoutInflater();
View rootLayout = inflater.inflate(yout.camera, null, false);
mCameraModuleRootView = rootLayout.findViewById(R.id.camera_app_root);
mPanoStitchingPanel = findViewById(R.id.pano_stitching_progress_panel);
mBottomProgress = (ProgressBar) findViewById(R.id.pano_stitching_progress_bar);
mCameraPreviewData = new CameraPreviewData(rootLayout,
FilmStripView.ImageData.SIZE_FULL, FilmStripView.ImageData.SIZE_FULL); // Put a CameraPreviewData at the first position.
mWrappedDataAdapter = new FixedFirstDataAdapter(
new CameraDataAdapter(new ColorDrawable(
getResources().getColor(R.color.photo_placeholder)) ),
mCameraPreviewData);
…
setModuleFromIndex(moduleIndex);
mCurrentModule.init(this, mCameraModuleRootView);
…
},
该函数主要设置activity视图,并根据传过来的intent来判读改启动photomodule还是videomodule,当从launcher 启动的时候moduleIndex肯定是0,所以会调用mCurrentModule = new PhotoModule();新建一个PhotoModule对象,该对象就是负责拍照相关的操作。
Step2:PhotoModule(),对象创立之后,并没有做实质性的动作,我们接着往下看
Step3:mCurrentModule.init(this,mCameraModuleRootVie w); mCurrentModule就是PhotoModule类的一个实例,public void init(CameraActivity activity, View parent) {
mActivity = activity;
mRootView = parent;
mUI = new PhotoUI(activity, this, parent); mPreferences = new
ComboPreferences(mActivity);
CameraSettings.upgradeGlobalPreferences(mPreferen ces.getGlobal());
mCameraId = getPreferredCameraId(mPreferences);
mContentResolver = mActivity.getContentResolver();
// Surface texture is from camera screen nail and startPreview needs it.
// This must be done before startPreview.
mIsImageCaptureIntent = isImageCaptureIntent();
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferenc es.getLocal());
// we need to reset exposure for the preview
resetExposureCompensation();
initializeControlByIntent();
mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK _CAPTURE, false);
mLocationManager = new LocationManager(mActivity, mUI);
mSensorManager = (SensorManager)(mActivity.getSystemService(Contex t.SENSOR_SERVICE));
brightnessProgressBar = (ProgressBar)mRootView.findViewById(R.id.progress );
if (brightnessProgressBar instanceof SeekBar) {
SeekBar seeker = (SeekBar) brightnessProgressBar;
seeker.setOnSeekBarChangeListener(mSeekListener); }
brightnessProgressBar.setMax(MAXIMUM_BRIGHTNESS);
brightnessProgressBar.setProgress(mbrightness);
skinToneSeekBar = (SeekBar) mRootView.findViewById(R.id.skintoneseek);
skinToneSeekBar.setOnSeekBarChangeListener(mskinT oneSeekListener);
skinToneSeekBar.setVisibility(View.INVISIBLE);
Title = (TextView)mRootView.findViewById(R.id.skintonetit le);
RightValue = (TextView)mRootView.findViewById(R.id.skintonerig ht);
LeftValue = (TextView)mRootView.findViewById(R.id.skintonelef t);
Storage.setSaveSDCard(
mPreferences.getString(CameraSettings.KEY_CAMERA_ SAVEPATH, "0").equals("1"));
}
刚刚介绍过Photomodule是负责camera照相功能的,主要协调界面的显示,参数的配置,方便用户根据自己的爱好来设置相关参数。
参数View parent,是拍照界面的根节点,即
在cameraactivity中inflate 的的camera_app_root视图。
Init函数中做了很多重要的工作。
创立UI视图,初始化根本参数,
Step4:new PhotoUI(activity, this, parent)
视图的真正创立是在PhotoUI对象中,我们接着往下看
public PhotoUI(CameraActivity activity, PhotoController controller, View parent) {
mActivity = activity;
mController = controller;
mRootView = parent;
mActivity.getLayoutInflater().inflate(yout.ph oto_module,
(ViewGroup) mRootView, true);
mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay);
mFlashOverlay = mRootView.findViewById(R.id.flash_overlay);
mPreviewCover = mRootView.findViewById(R.id.preview_cover);
// display the view
mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content);
mTextureView.setSurfaceTextureListener(this);
mTextureView.addOnLayoutChangeListener(mLayoutLis tener);
initIndicators();
mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
mSwitcher = (ModuleSwitcher) mRootView.findViewById(R.id.camera_switcher);
mSwitcher.setCurrentIndex(ModuleSwitcher.PHOTO_MO DULE_INDEX);
mSwitcher.setSwitchListener(mActivity);
mMenuButton = mRootView.findViewById(R.id.menu);
ViewStub faceViewStub = (ViewStub) mRootView .findViewById(R.id.face_view_stub); if (faceViewStub != null) {
faceViewStub.inflate();
mFaceView = (FaceView) mRootView.findViewById(R.id.face_view);
setSurfaceTextureSizeChangedListener(mFaceView); }
mCameraControls = (CameraControls) mRootView.findViewById(R.id.camera_controls);
mAnimationManager = new AnimationManager();
mOrientationResize = false;
mPrevOrientationResize = false;
}
函数首先inflate 视图,挂在mRootView节点下,
mRootView即是中的
camera_app_root视图,他是photomodule的根视图。
photo_module这个视图包括了其他的一些重要视图,其中比较重要的几个mTextureView,mShutterButton,mSwitcher,faceViewStub,mCameraControls,mMenuButton等mTextureView:是TextureView控件,和surfaceview功能差不多,只是实现机制不同,都是用来显示流媒体的。
Camera preview数据就在此显示
mCameraControls:是个容器,包裹mShutterButton,mSwitcher,PieMenuButton,等控件
mShutterButton:拍照按钮,mSwitcher:模式切换,faceViewStub脸部扑捉。
mMenuButton:设置参数相关的
step5:cameraactivity.onresume()
界面和参数的初始化工作完成之后,camera activity进去resume状态,
public void onResume() {
…
mOrientationListener.enable();
mCurrentModule.onResumeBeforeSuper();
super.onResume();
mCurrentModule.onResumeAfterSuper();
setSwipingEnabled(true);
….
}
这里掉用了一个重要的函数mCurrentModule.onResumeAfterSuper();到目前为止我们还没有看到camera设备被翻开的过程,什么原因,以前在oncreate的时候就翻开了camera设备,难道是我们在前面分析的时候漏掉了,客官别急,切往下看。
Step6,mCurrentModule.onResumeAfterSuper()
调用这个函数之后,又进入到photomodule对象中了,我们来看一下具体实现
public void onResumeAfterSuper() {
String action = mActivity.getIntent().getAction();
if
(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA.equals (action)
||
MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE. equals(action)) {
Log.v(TAG, "On resume, from lock screen.");
mHandler.postDelayed(new Runnable() {
public void run() {
onResumeTasks();
}
}, ON_RESUME_TASKS_DELAY_MSEC);
} else {
Log.v(TAG, "On resume.");
onResumeTasks();
}
mHandler.post(new Runnable(){
@Override
public void run(){
mActivity.updateStorageSpaceAndHint();
}
});
}
函数先根据action类型做不同的处理,最终都会调用onResumeTasks函数。
Step7:onResumeTasks();
private void onResumeTasks() {
if (mOpenCameraFail || mCameraDisabled) return;
mJpegPictureCallbackTime = 0;
mZoomValue = 0;
resetExposureCompensation();
if (!prepareCamera()) {
// Camera failure.
return;
}
函数接着调用prepareCamera进一步启动camera设备
Step8:prepareCamera()
private boolean prepareCamera() {
mCameraDevice = CameraUtil.openCamera(
mActivity, mCameraId, mHandler,
mActivity.getCameraOpenErrorCallback());
if (mCameraDevice == null) {
Log.e(TAG, "Failed to open camera:" + mCameraId);
return false;
}
mParameters = mCameraDevice.getParameters();
initializeCapabilities();
if (mFocusManager == null) initializeFocusManager();
setCameraParameters(UPDATE_PARAM_ALL);
mHandler.sendEmptyMessage(CAMERA_OPEN_DONE);
mCameraPreviewParamsReady = true;
startPreview();
mOnResumeTime = SystemClock.uptimeMillis(); checkDisplayRotation();
return true;
}
这个是很重要的函数,函数先调用
来获取camera设备,我们在上一篇文章中介绍过了,这里不做介绍了。
获取到camera设备后,接着设置camera初始化参数,最后调用startPreview();启动预览。
在启动预览
的时候mHandler.sendEmptyMessage(CAMERA_OPEN_DONE);向mHandler发送了一个CAMERA_OPEN_DONE消息。
Camera setting的局部测初始化是在这个阶段完成的。
Step10:private void onCameraOpened()
{
View root = mUI.getRootView();
int width = root.getWidth();
int height = root.getHeight();
mFocusManager.setPreviewSize(width, height); openCameraCommon();
resizeForPreviewAspectRatio();
}
该函数还是比较简单的,设置mFocusManager区域大小,调用openCameraCommon进一步操作camera
Step11:openCameraCommon();
private void openCameraCommon() {
loadCameraPreferences();
mUI.onCameraOpened(mPreferenceGroup, mPreferences, mParameters, this);
if (mIsImageCaptureIntent) {
mUI.overrideSettings(CameraSettings.KEY_CAMERA_HDR_ PLUS,
mActivity.getString(R.string.setting_off_value));
}
updateCameraSettings();
showTapToFocusToastIfNeeded();
}
函数首先调用loadCameraPreferences函数,来加载默认初始数据,将这些初始数据加载到内存中,最终保存在mPreferenceGroup变量中,被后面的UI空间使用。
Step14:mUI.onCameraOpened(mPreferenceGroup, mPreferences, mParameters, this);
加载完初始数据之后,下一步便是创立必要的UI控件public void onCameraOpened(PreferenceGroup prefGroup, ComboPreferences prefs,
Camera.Parameters params, OnPreferenceChangedListener listener) {
if (mPieRenderer == null) {
mPieRenderer = new PieRenderer(mActivity);
mPieRenderer.setPieListener(this);
mRenderOverlay.addRenderer(mPieRenderer);
}
if (mMenu == null) {
mMenu = new PhotoMenu(mActivity, this, mPieRenderer);
mMenu.setListener(listener);
}
mMenu.initialize(prefGroup);
mMenuInitialized = true;
if (mZoomRenderer == null) {
mZoomRenderer = new ZoomRenderer(mActivity);
mRenderOverlay.addRenderer(mZoomRenderer);
}
if (mGestures == null) {
// this will handle gesture disambiguation
and dispatching
mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer);
mRenderOverlay.setGestures(mGestures);
}
mGestures.setZoomEnabled(params.isZoomSupported()); mGestures.setRenderOverlay(mRenderOverlay); mRenderOverlay.requestLayout();
initializeZoom(params);
updateOnScreenIndicators(params, prefGroup, prefs);
}
PhotoMenu这对象控制在屏幕上出现的各个小按钮.视图的大体层次见以下图
zoomview CameraControl RenderOverla Framelayout
TextureView
PieMenuButton FrameLayout
indicators ModuleSwitch ShutterBut
FilmStripView CameraRootView。