Android -- Camera源碼簡析,啟動流程
com.android.camera.Camera.java,主要的實現(xiàn)Activity,繼承于ActivityBase。
ActivityBase
在ActivityBase中執(zhí)行流程:
onCreate中進(jìn)行判斷是否是平板;
onResume中判斷是否鎖屏,鎖屏&camera不存在時候,mOnResumePending置為true,否則置為false并執(zhí)行doOnResume;
onWindowFocusChanged中判斷是否獲取到焦點&mOnResumePending,滿足的話執(zhí)行doOnResume;
onPause中將mOnResumePending置為false;
Camera.java
接下來分析Camera.java,執(zhí)行流程:
1、onCreate
復(fù)制代碼
// 獲得攝像頭的數(shù)量,前置和后置
getPreferredCameraId();
// 獲得對焦設(shè)置eg:連續(xù)對焦或者其它
String[] defaultFocusModes = getResources().getStringArray(R.array.pref_camera_focusmode_default_array);
//實例化Focus管理對象
mFocusManager = new FocusManager(mPreferences, defaultFocusModes);
// 開啟線程來啟動攝像頭
mCameraOpenThread.start();
// 是否是第三方應(yīng)用啟動拍照功能
mIsImageCaptureIntent = isImageCaptureIntent();
// 設(shè)置UI布局文件
setContentView(R.layout.camera);
if (mIsImageCaptureIntent) {
// 當(dāng)?shù)谌狡渌团恼眨枰@示不同的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);
}
// 一個能旋轉(zhuǎn)的dialog.比如相機設(shè)置的dialog,這個類實現(xiàn)了旋轉(zhuǎn)的父類
mRotateDialog = new RotateDialogController(this, R.layout.rotate_dialog);
// 設(shè)置camera的ID,寫道SharedPreference中
mPreferences.setLocalId(this, mCameraId);
// 更新preference
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
// 獲得相機數(shù)
mNumberOfCameras = CameraHolder.instance().getNumberOfCameras();
// 貌似是獲得是否是快速拍照
mQuickCapture = getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false);
// 為當(dāng)前的preview重置曝光值
resetExposureCompensation();
// 隱藏系統(tǒng)導(dǎo)航欄等
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的線程執(zhí)行完后,當(dāng)前的線程才開始運行。主要是為了確保camera設(shè)備被打開了
mCameraOpenThread.join();
// 線程執(zhí)行完后置為空來讓系統(tǒng)回收資源
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 設(shè)置拍照的參數(shù)
setupCaptureParams();
} else {
//設(shè)置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;
復(fù)制代碼
2、surfaceCreated
啥都沒做
3、surfaceChanged
復(fù)制代碼
// 確保在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[!--empirenews.page--]
// 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();
}
復(fù)制代碼
如果是第一次加載,則執(zhí)行mHandler.sendEmptyMessage(FIRST_TIME_INIT); 對應(yīng)處理的是initializeFirstTime();
復(fù)制代碼
/**
* 初始化,第一次初始化
* // 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());
// 初始化屏幕最上方的標(biāo)志,比如開啟了曝光值啊,什么的
initOnScreenIndicator();
// 位置服務(wù)
mLocationManager.recordLocation(recordLocation);
keepMediaProviderInstance();
// 檢查存儲空間和初始化儲存目錄
checkStorage();
// Initialize last picture button.
mContentResolver = getContentResolver();
if (!mIsImageCaptureIntent) { // no thumbnail in image capture intent
// 初始化縮略圖
initThumbnailButton();
}
// Initialize shutter button.
// 初始化拍照按鈕并設(shè)置監(jiān)聽事件
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();
// 設(shè)置屏幕亮度
Util.initializeScreenBrightness(getWindow(), getContentResolver());
// 注冊SD卡相關(guān)的廣播,比如拔出存儲卡什么的
installIntentFilter();
// 初始化縮放UI
initializeZoom();
// 更新屏幕上的閃光燈什么的標(biāo)記
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();
}
復(fù)制代碼
如果不是,則執(zhí)行initializeSecondTime();
復(fù)制代碼
/**
* // 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.
//方向翻轉(zhuǎn)設(shè)置enable,其中包括翻轉(zhuǎn)的時候的動畫
mOrientationListener.enable();
// Start location update if needed.[!--empirenews.page--]
boolean recordLocation = RecordLocationPreference.get(
mPreferences, getContentResolver());
mLocationManager.recordLocation(recordLocation);
//設(shè)置SD卡廣播
installIntentFilter();
mImageSaver = new ImageSaver();
//初始化Zoom
initializeZoom();
//mMediaProviderClient=媒體Provider對象
keepMediaProviderInstance();
//檢查硬盤
checkStorage();
//淡出retake和done的Button
hidePostCaptureAlert();
if (!mIsImageCaptureIntent) {
//如果不是第三方開啟,則更新縮略圖
updateThumbnailButton();
mModePicker.setCurrentMode(ModePicker.MODE_CAMERA);
}
}
復(fù)制代碼
4、surfaceDestroyed
stopPreview();
mSurfaceHolder = null;