zoukankan      html  css  js  c++  java
  • 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;

    我是天王盖地虎的分割线                                                             

  • 相关阅读:
    第九章:switch语句
    第八章:if-else语句
    第七章:运算符及运用
    第六章:名命规范
    事务
    jdbc
    Object
    容器
    Java exception
    Java OO1
  • 原文地址:https://www.cnblogs.com/yydcdut/p/4125128.html
Copyright © 2011-2022 走看看