Android -- Camera源碼簡析,啟動流程


com.android.camera.Camera.java,主要的實現Activity,繼承於ActivityBase。

ActivityBase                                                                          

在ActivityBase中執行流程:

  1. onCreate中進行判斷是否是平板;
  2. onResume中判斷是否鎖屏,鎖屏&camera不存在時候,mOnResumePending置為true,否則置為false並執行doOnResume;
  3. onWindowFocusChanged中判斷是否獲取到焦點&mOnResumePending,滿足的話執行doOnResume;
  4. 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;

我是天王蓋地虎的分割線                                                             


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM