Android -- Camera源码简析,启动流程
com.android.camera.Camera.java,主要的实现Activity,继承于ActivityBase。
ActivityBase
在ActivityBase中执行流程:
- onCreate中进行判断是否是平板;
- onResume中判断是否锁屏,锁屏&camera不存在时候,mOnResumePending置为true,否则置为false并执行doOnResume;
- onWindowFocusChanged中判断是否获取到焦点&mOnResumePending,满足的话执行doOnResume;
- onPause中将mOnResumePending置为false;
Camera.java
接下来分析Camera.java,执行流程:
1、onCreate
// 获得摄像头的数量,前置和后置 getPreferredCameraId(); // 获得对焦设置eg:连续对焦或者其它 String[] defaultFocusModes = getResources().getStringArray(R.array.pref_camera_focusmode_default_array); //实例化Focus管理对象 mFocusManager = new FocusManager(mPreferences, defaultFocusModes); // 开启线程来启动摄像头 mCameraOpenThread.start(); // 是否是第三方应用启动拍照功能 mIsImageCaptureIntent = isImageCaptureIntent(); // 设置UI布局文件 setContentView(R.layout.camera); if (mIsImageCaptureIntent) { // 当第三方其送拍照,需要显示不同的UI,比如取消键盘 mReviewDoneButton = (Rotatable) findViewById(R.id.btn_done); mReviewCancelButton = (Rotatable) findViewById(R.id.btn_cancel); findViewById(R.id.btn_cancel).setVisibility(View.VISIBLE); } else { // 反之显示缩略图 mThumbnailView = (RotateImageView) findViewById(R.id.thumbnail); mThumbnailView.enableFilter(false); mThumbnailView.setVisibility(View.VISIBLE); } // 一个能旋转的dialog.比如相机设置的dialog,这个类实现了旋转的父类 mRotateDialog = new RotateDialogController(this, R.layout.rotate_dialog); // 设置camera的ID,写道SharedPreference中 mPreferences.setLocalId(this, mCameraId); // 更新preference CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); // 获得相机数 mNumberOfCameras = CameraHolder.instance().getNumberOfCameras(); // 貌似是获得是否是快速拍照 mQuickCapture = getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false); // 为当前的preview重置曝光值 resetExposureCompensation(); // 隐藏系统导航栏等 Util.enterLightsOutMode(getWindow()); //SurfaceView SurfaceView preview = (SurfaceView) findViewById(R.id.camera_preview); SurfaceHolder holder = preview.getHolder(); holder.addCallback(this); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); try { // 这个join语句就是为了保证openCamera的线程执行完后,当前的线程才开始运行。主要是为了确保camera设备被打开了 mCameraOpenThread.join(); // 线程执行完后置为空来让系统回收资源 mCameraOpenThread = null; if (mOpenCameraFail) { // 打开camera失败,显示“无法连接到相机” Util.showErrorAndFinish(this, R.string.cannot_connect_camera); return; } else if (mCameraDisabled) { // 由于安全政策限制,相机已被停用 Util.showErrorAndFinish(this, R.string.camera_disabled); return; } } catch (InterruptedException ex) { // ignore } //开启显示的子线程 mCameraPreviewThread.start(); if (mIsImageCaptureIntent) { //如果是第三方开启的 ,setupCaptureParams 设置拍照的参数 setupCaptureParams(); } else { //设置ModePicker mModePicker = (ModePicker) findViewById(R.id.mode_picker); mModePicker.setVisibility(View.VISIBLE); mModePicker.setOnModeChangeListener(this); mModePicker.setCurrentMode(ModePicker.MODE_CAMERA); } mZoomControl = (ZoomControl) findViewById(R.id.zoom_control); mOnScreenIndicators = (Rotatable) findViewById(R.id.on_screen_indicators); mLocationManager = new LocationManager(this, this); //摄像头ID mBackCameraId = CameraHolder.instance().getBackCameraId(); mFrontCameraId = CameraHolder.instance().getFrontCameraId(); // 在startPreview里面有notify方法 synchronized (mCameraPreviewThread) { try { mCameraPreviewThread.wait(); } catch (InterruptedException ex) { // ignore } } // 初始化各种控制按钮 initializeIndicatorControl(); //初始化拍照声音 mCameraSound = new CameraSound(); try { //确保显示 mCameraPreviewThread.join(); } catch (InterruptedException ex) { // ignore } mCameraPreviewThread = null;
2、surfaceCreated
啥都没做
3、surfaceChanged
// 确保在holder中有surface if (holder.getSurface() == null) { Log.d(TAG, "holder.getSurface() == null"); return; } // We need to save the holder for later use, even when the mCameraDevice // is null. This could happen if onResume() is invoked after this // function. mSurfaceHolder = holder; if (mCameraDevice == null) return; if (mPausing || isFinishing()) return; // Set preview display if the surface is being created. Preview was // already started. Also restart the preview if display rotation has // changed. Sometimes this happens when the device is held in portrait // and camera app is opened. Rotation animation takes some time and // display rotation in onCreate may not be what we want. if (mCameraState == PREVIEW_STOPPED) { startPreview(); startFaceDetection(); } else { if (Util.getDisplayRotation(this) != mDisplayRotation) { setDisplayOrientation(); } if (holder.isCreating()) { // Set preview display if the surface is being created and preview // was already started. That means preview display was set to null // and we need to set it now. setPreviewDisplay(holder); } } // If first time initialization is not finished, send a message to do // it later. We want to finish surfaceChanged as soon as possible to let // user see preview first. if (!mFirstTimeInitialized) { mHandler.sendEmptyMessage(FIRST_TIME_INIT); } else { initializeSecondTime(); }
如果是第一次加载,则执行mHandler.sendEmptyMessage(FIRST_TIME_INIT); 对应处理的是initializeFirstTime();
/** * 初始化,第一次初始化 * // Snapshots can only be taken after this is called. It should be called * // once only. We could have done these things in onCreate() but we want to * // make preview screen appear as soon as possible. */ private void initializeFirstTime() { if (mFirstTimeInitialized) return; // Create orientation listenter. This should be done first because it // takes some time to get first orientation. mOrientationListener = new MyOrientationEventListener(Camera.this); mOrientationListener.enable(); // Initialize location sevice. boolean recordLocation = RecordLocationPreference.get( mPreferences, getContentResolver()); // 初始化屏幕最上方的标志,比如开启了曝光值啊,什么的 initOnScreenIndicator(); // 位置服务 mLocationManager.recordLocation(recordLocation); keepMediaProviderInstance(); // 检查存储空间和初始化储存目录 checkStorage(); // Initialize last picture button. mContentResolver = getContentResolver(); if (!mIsImageCaptureIntent) { // no thumbnail in image capture intent // 初始化缩略图 initThumbnailButton(); } // Initialize shutter button. // 初始化拍照按钮并设置监听事件 mShutterButton = (ShutterButton) findViewById(R.id.shutter_button); mShutterButton.setOnShutterButtonListener(this); mShutterButton.setVisibility(View.VISIBLE); // Initialize focus UI. mPreviewFrame = findViewById(R.id.camera_preview); mPreviewFrame.setOnTouchListener(this); // 聚焦框 mFocusAreaIndicator = (RotateLayout) findViewById(R.id.focus_indicator_rotate_layout); CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); mFocusManager.initialize(mFocusAreaIndicator, mPreviewFrame, mFaceView, this, mirror, mDisplayOrientation); // 初始化一个图片的保存线程 mImageSaver = new ImageSaver(); // 设置屏幕亮度 Util.initializeScreenBrightness(getWindow(), getContentResolver()); // 注册SD卡相关的广播,比如拔出存储卡什么的 installIntentFilter(); // 初始化缩放UI initializeZoom(); // 更新屏幕上的闪光灯什么的标记 updateOnScreenIndicators(); // 开始面部检测 startFaceDetection(); // Show the tap to focus toast if this is the first start. // 假如是第一次启动,提示用户“触摸对焦” if (mFocusAreaSupported && mPreferences.getBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, true)) { // Delay the toast for one second to wait for orientation. mHandler.sendEmptyMessageDelayed(SHOW_TAP_TO_FOCUS_TOAST, 1000); } mFirstTimeInitialized = true; addIdleHandler(); }
如果不是,则执行initializeSecondTime();
/** * // If the activity is paused and resumed, this method will be called in * // onResume. */ private void initializeSecondTime() { // Start orientation listener as soon as possible because it takes // some time to get first orientation. //方向翻转设置enable,其中包括翻转的时候的动画 mOrientationListener.enable(); // Start location update if needed. boolean recordLocation = RecordLocationPreference.get( mPreferences, getContentResolver()); mLocationManager.recordLocation(recordLocation); //设置SD卡广播 installIntentFilter(); mImageSaver = new ImageSaver(); //初始化Zoom initializeZoom(); //mMediaProviderClient=媒体Provider对象 keepMediaProviderInstance(); //检查硬盘 checkStorage(); //淡出retake和done的Button hidePostCaptureAlert(); if (!mIsImageCaptureIntent) { //如果不是第三方开启,则更新缩略图 updateThumbnailButton(); mModePicker.setCurrentMode(ModePicker.MODE_CAMERA); } }
4、surfaceDestroyed
stopPreview(); mSurfaceHolder = null;
我是天王盖地虎的分割线
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。