Android9.0 Camera App代码跟踪

    各位早上好,这次给大家带来的是Android9.0 Camera App的代码阅读,即是工作需要也是个人的笔记,帮助大家学习。

Android9.0 Camera App源代码的位置(/android/packages/apps/SnapdragonCamera),其他的Camera App在Android9.0中已经弃用了,我把源码导入到Android studio中让大家看看它的代码结构,如图:

Android9.0 Camera App代码跟踪_第1张图片Android9.0 Camera App代码跟踪_第2张图片

这里着重要讲的是src里面的Java代码,导入到Android studio会有很多错误,博主一开始天真地以为可以在Android studio里面编译,但发现错误太多不现实,还是在源码里面编译吧,android studio就作为代码阅读工具用,大家也可以用source insight阅读,至于博主,两个都用。

好了,废话不多说我们开始阅读代码吧。

第一个问题:Carmera App是怎么启动的?

有Android App开发基础的同学就知道,Android App启动的时候第一个启动的就是Application.那么这个类在哪里,我们可以找到AndroidManifest.xml文件来看

Android9.0 Camera App代码跟踪_第3张图片

看在这里,我们找到com.android.camera.app.CameraApp先

Android9.0 Camera App代码跟踪_第4张图片

look!看到了吧。好现在来看看它做了哪些工作,一般来讲这个类肯定是做一些初始化的工作。我们看他的源码:

@Override
    public void onCreate() {
        super.onCreate();
        ActivityManager actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
        actManager.getMemoryInfo(memInfo);
        mMaxSystemMemory = memInfo.totalMem;
        if(mMaxSystemMemory <= LOW_MEMORY_DEVICE_THRESHOLD) {//检查设备的存储空间是否充足
            mIsLowMemoryDevice = true;
        }
        SettingsManager.createInstance(this);//实例化一个Camera设置管理类
        UsageStatistics.initialize(this);
        CameraUtil.initialize(this);//Camrera工具类初始化
        SDCard.initialize(this);//SD卡初始化
    }

这里面Camre是存储空间需求比较大的应用,所以有个最低内存要求。

接下来要看看App启动的第一个界面,我们再看一下AndroidManifest.xml里面的代码:


            
                //这个Activity作为主界面启动
                
            

            
            
        

我们找到com.android.camera.CameraActivity类,这个类代码比较多我就只摘取其中的片段来讲。

首先我们找到Actively的生命周期方法onCreate()这是Activity启动是首先要执行的方法,这里面做了什么工作呢?我们来看下源码:

@Override
    public void onCreate(Bundle state) {
        super.onCreate(state);
        // Check if this is in the secure camera mode.
        Intent intent = getIntent();
        String action = intent.getAction();//Activity启动会携带相应的action,根据action可以判断Activity是从哪里启动的
        if (INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action)
                || ACTION_IMAGE_CAPTURE_SECURE.equals(action)
                || intent.getComponent().getClassName().equals(GESTURE_CAMERA_NAME)) {
            mSecureCamera = true;
        } else {
            mSecureCamera = intent.getBooleanExtra(SECURE_CAMERA_EXTRA, false);
        }

        if (mSecureCamera) {//什么是secure camera mode?就是你在锁屏状态下进入的Camera,这种状态是的Camera功能是有限制的
            // Change the window flags so that secure camera can show when locked
            Window win = getWindow();
            WindowManager.LayoutParams params = win.getAttributes();
            params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
            if (intent.getComponent().getClassName().equals(GESTURE_CAMERA_NAME)) {
                params.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
                PowerManager pm = ((PowerManager) getSystemService(POWER_SERVICE));
                mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
                mWakeLock.acquire();
                Log.d(TAG, "acquire wake lock");
            }
            win.setAttributes(params);
        }
//这里检查App是否有相关的权限
        if (mSecureCamera && !hasCriticalPermissions()) {
            return;
        }

        if (isStartRequsetPermission()) {
            Log.v(TAG, "onCreate: Missing critical permissions.");
            finish();
            return;
        }

        boolean camera_api_1_support = true;
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
//检查设备的api是否支持
        if (!sharedPreferences.contains(CAMERA_API_1_SUPPORT)) {
            camera_api_1_support = cameraAPICheck();
        } else {
            camera_api_1_support = sharedPreferences.getBoolean(CAMERA_API_1_SUPPORT,true);
        }

        mCursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                null, null, null, null);
        GcamHelper.init(getContentResolver());

        getWindow().requestFeature(Window.FEATURE_ACTION_BAR);

        LayoutInflater inflater = getLayoutInflater();
//获取View
        View rootLayout = inflater.inflate(R.layout.camera, null, false);
        mCameraRootFrame = (FrameLayout)rootLayout.findViewById(R.id.camera_root_frame);
        mCameraPhotoModuleRootView = rootLayout.findViewById(R.id.camera_photo_root);
        mCameraVideoModuleRootView = rootLayout.findViewById(R.id.camera_video_root);
        mCameraPanoModuleRootView = rootLayout.findViewById(R.id.camera_pano_root);
        mCameraCaptureModuleRootView = rootLayout.findViewById(R.id.camera_capture_root);
//界面根据moduleIndex来决定加载那个module
        int moduleIndex = -1;
        if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(getIntent().getAction())
                || MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())) {
            moduleIndex = ModuleSwitcher.VIDEO_MODULE_INDEX;
        } else if (MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA.equals(getIntent().getAction())
                || MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(getIntent()
                .getAction())) {
            moduleIndex = ModuleSwitcher.PHOTO_MODULE_INDEX;
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
            if (prefs.getInt(CameraSettings.KEY_STARTUP_MODULE_INDEX, -1)
                    == ModuleSwitcher.GCAM_MODULE_INDEX && GcamHelper.hasGcamCapture()) {
                moduleIndex = ModuleSwitcher.GCAM_MODULE_INDEX;
            }
        } else if (MediaStore.ACTION_IMAGE_CAPTURE.equals(getIntent().getAction())
                || MediaStore.ACTION_IMAGE_CAPTURE_SECURE.equals(getIntent().getAction())) {
            moduleIndex = ModuleSwitcher.PHOTO_MODULE_INDEX;
        } else {
            // If the activity has not been started using an explicit intent,
            // read the module index from the last time the user changed modes
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
            moduleIndex = prefs.getInt(CameraSettings.KEY_STARTUP_MODULE_INDEX, -1);
            if ((moduleIndex == ModuleSwitcher.GCAM_MODULE_INDEX &&
                    !GcamHelper.hasGcamCapture()) || moduleIndex < 0) {
                moduleIndex = ModuleSwitcher.PHOTO_MODULE_INDEX;
            }
        }
        boolean cam2on = PersistUtil.getCamera2Mode();
        if (!cam2on && !camera_api_1_support)
            cam2on = true;
        CameraHolder.setCamera2Mode(this, cam2on);
        if (cam2on && (moduleIndex == ModuleSwitcher.PHOTO_MODULE_INDEX ||
                moduleIndex == ModuleSwitcher.VIDEO_MODULE_INDEX))
            moduleIndex = ModuleSwitcher.CAPTURE_MODULE_INDEX;

        mOrientationListener = new MyOrientationEventListener(this);
        setContentView(R.layout.camera_filmstrip);
        mFilmStripView = (FilmStripView) findViewById(R.id.filmstrip_view);
        setModuleFromIndex(moduleIndex);//根据moduleIndex切换到相应的模块

        mActionBar = getActionBar();
        mActionBar.addOnMenuVisibilityListener(this);

        if (ApiHelper.HAS_ROTATION_ANIMATION) {
            setRotationAnimation();
        }

        mMainHandler = new MainHandler(getMainLooper());

        mAboveFilmstripControlLayout =
                (FrameLayout) findViewById(R.id.camera_above_filmstrip_layout);
        mAboveFilmstripControlLayout.setFitsSystemWindows(true);
        mPanoramaManager = AppManagerFactory.getInstance(this)
                .getPanoramaStitchingManager();
        mPlaceholderManager = AppManagerFactory.getInstance(this)
                .getGcamProcessingManager();
        mPanoramaManager.addTaskListener(mStitchingListener);
        mPlaceholderManager.addTaskListener(mPlaceholderListener);
        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);

        mFilmStripView.setViewGap(
                getResources().getDimensionPixelSize(R.dimen.camera_film_strip_gap));
        mPanoramaViewHelper = new PanoramaViewHelper(this);
        mPanoramaViewHelper.onCreate();
        mFilmStripView.setPanoramaViewHelper(mPanoramaViewHelper);
        // Set up the camera preview first so the preview shows up ASAP.
        mFilmStripView.setListener(mFilmStripListener);

        if (!mSecureCamera) {
            mDataAdapter = mWrappedDataAdapter;
            mFilmStripView.setDataAdapter(mDataAdapter);
            if (!isCaptureIntent()) {
                mDataAdapter.requestLoad(getContentResolver());
                mDataRequested = true;
            }
        } else {
            // Put a lock placeholder as the last image by setting its date to
            // 0.
            ImageView v = (ImageView) getLayoutInflater().inflate(
                    R.layout.secure_album_placeholder, null);
            v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    try {
                        UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
                                UsageStatistics.ACTION_GALLERY, null);
                        startActivity(IntentHelper.getGalleryIntent(CameraActivity.this));
                    } catch (ActivityNotFoundException e) {
                        Log.w(TAG, "Failed to launch gallery activity, closing");
                    }
                    finish();
                }
            });
            mDataAdapter = new FixedLastDataAdapter(
                    mWrappedDataAdapter,
                    new SimpleViewData(
                            v,
                            v.getDrawable().getIntrinsicWidth(),
                            v.getDrawable().getIntrinsicHeight(),
                            0, 0));
            // Flush out all the original data.
            mDataAdapter.flush();
            mFilmStripView.setDataAdapter(mDataAdapter);
        }

        setupNfcBeamPush();

        mLocalImagesObserver = new LocalMediaObserver();
        mLocalVideosObserver = new LocalMediaObserver();

        getContentResolver().registerContentObserver(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true,
                mLocalImagesObserver);
        getContentResolver().registerContentObserver(
                MediaStore.Video.Media.EXTERNAL_CONTENT_URI, true,
                mLocalVideosObserver);

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        mDeveloperMenuEnabled = prefs.getBoolean(CameraSettings.KEY_DEVELOPER_MENU, false);

        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        int width = size.x;
        int height = size.y;

        int lower = Math.min(width, height);

        int offset = lower * 7 / 100;
        SETTING_LIST_WIDTH_1 = lower / 2 + offset;
        SETTING_LIST_WIDTH_2 = lower / 2 - offset;
        registerSDcardMountedReceiver();

        mAutoTestEnabled = PersistUtil.isAutoTestEnabled();

        if (mAutoTestEnabled) {
            registerAutoTestReceiver();
        }
    }

我们重点看下setModuleFromIndex(int moduleIndex) 方法,这个方法会根据moduleIndex切换到相应的模块界面去

/**
     * Sets the mCurrentModuleIndex, creates a new module instance for the given
     * index an sets it as mCurrentModule.
     */
    private void setModuleFromIndex(int moduleIndex) {
        mCameraPhotoModuleRootView.setVisibility(View.GONE);
        mCameraVideoModuleRootView.setVisibility(View.GONE);
        mCameraPanoModuleRootView.setVisibility(View.GONE);
        mCameraCaptureModuleRootView.setVisibility(View.GONE);
        mCurrentModuleIndex = moduleIndex;
        switch (moduleIndex) {
            case ModuleSwitcher.VIDEO_MODULE_INDEX:
                if(mVideoModule == null) {
                    mVideoModule = new VideoModule();//视频模块
                    mVideoModule.init(this, mCameraVideoModuleRootView);
                } else {
                    mVideoModule.reinit();
                }
                mCurrentModule = mVideoModule;
                mCameraVideoModuleRootView.setVisibility(View.VISIBLE);
                break;

            case ModuleSwitcher.PHOTO_MODULE_INDEX:
                if(mPhotoModule == null) {
                    mPhotoModule = new PhotoModule();//拍照模块
                    mPhotoModule.init(this, mCameraPhotoModuleRootView);
                } else {
                    mPhotoModule.reinit();
                }
                mCurrentModule = mPhotoModule;
                mCameraPhotoModuleRootView.setVisibility(View.VISIBLE);
                break;

            case ModuleSwitcher.WIDE_ANGLE_PANO_MODULE_INDEX:
                if(mPanoModule == null) {
                    mPanoModule = new WideAnglePanoramaModule();//全景广角模块
                    mPanoModule.init(this, mCameraPanoModuleRootView);
                }
                mCurrentModule = mPanoModule;
                mCameraPanoModuleRootView.setVisibility(View.VISIBLE);
                break;

            case ModuleSwitcher.CAPTURE_MODULE_INDEX:
                if(mCaptureModule == null) {
                    mCaptureModule = new CaptureModule();//快照
                    mCaptureModule.init(this, mCameraCaptureModuleRootView);
                } else {
                    mCaptureModule.reinit();
                }
                mCurrentModule = mCaptureModule;
                mCameraCaptureModuleRootView.setVisibility(View.VISIBLE);
                break;

            case ModuleSwitcher.PANOCAPTURE_MODULE_INDEX:
                final Activity activity = this;
                if(!PanoCaptureProcessView.isSupportedStatic()) {
                    this.runOnUiThread(new Runnable() {
                        public void run() {
                            RotateTextToast.makeText(activity, "Panocapture library is missing", Toast.LENGTH_SHORT).show();
                        }
                    });
                    mCurrentModuleIndex = ModuleSwitcher.PHOTO_MODULE_INDEX;
                    //Let it fall through to photo module
                } else {
                    if (mPano2Module == null) {
                        mPano2Module = new PanoCaptureModule();//全景快照
                        mPano2Module.init(this, mCameraPanoModuleRootView);
                    }
                    mCurrentModule = mPano2Module;
                    mCameraPanoModuleRootView.setVisibility(View.VISIBLE);
                    break;
                }
            case ModuleSwitcher.LIGHTCYCLE_MODULE_INDEX: //Unused module for now
            case ModuleSwitcher.GCAM_MODULE_INDEX:  //Unused module for now
            default:
                // Fall back to photo mode.
                if(mPhotoModule == null) {
                    mPhotoModule = new PhotoModule();//默认使用拍照模块
                    mPhotoModule.init(this, mCameraPhotoModuleRootView);
                } else {
                    mPhotoModule.reinit();
                }
                mCurrentModule = mPhotoModule;
                mCameraPhotoModuleRootView.setVisibility(View.VISIBLE);
                break;
        }
    }

可以看到分别有,视频,拍照,全景等模块,这里面默认使用拍照模块(PhotoModule),我们来看下PhotoModule是什么玩意:

public class PhotoModule
        implements CameraModule,
        PhotoController,
        FocusOverlayManager.Listener,
        CameraPreference.OnPreferenceChangedListener,
        ShutterButton.OnShutterButtonListener,
        MediaSaveService.Listener,
        OnCountDownFinishedListener,
        LocationManager.Listener,
        SensorEventListener, MakeupLevelListener {
public interface CameraModule {

    public void init(CameraActivity activity, View frame);

    public void onPreviewFocusChanged(boolean previewFocused);

    public void onPauseBeforeSuper();

    public void onPauseAfterSuper();

    public void onResumeBeforeSuper();

    public void onResumeAfterSuper();

    public void onConfigurationChanged(Configuration config);

    public void onStop();

    public void onDestroy();

    public void installIntentFilter();

    public void onActivityResult(int requestCode, int resultCode, Intent data);

    public boolean onBackPressed();

    public boolean onKeyDown(int keyCode, KeyEvent event);

    public boolean onKeyUp(int keyCode, KeyEvent event);

    public void onSingleTapUp(View view, int x, int y);

    public void onPreviewTextureCopied();

    public void onCaptureTextureCopied();

    public void onUserInteraction();

    public boolean updateStorageHintOnResume();

    public void onOrientationChanged(int orientation);

    public void onShowSwitcherPopup();

    public void onMediaSaveServiceConnected(MediaSaveService s);

    public boolean arePreviewControlsVisible();

    public void resizeForPreviewAspectRatio();

    public void onSwitchSavePath();

    public void waitingLocationPermissionResult(boolean waiting);

    public void enableRecordingLocation(boolean enable);

    public void setPreferenceForTest(String key, String value);
}

它实现了CameraModule 接口,这个接口定义了Camera从创建到释放的过程,我们来看下init()方法:

@Override
    public void init(CameraActivity activity, View parent) {
        ...
        if (mOpenCameraThread == null) {
            mOpenCameraThread = new OpenCameraThread();//启动一个线程
            mOpenCameraThread.start();
        }
        ...
    }

 private class OpenCameraThread extends Thread {
        @Override
        public void run() {
            openCamera();//打开Camera
            startPreview();//开启预览
        }
    }

private void openCamera() {
        ...
//创建一个Camera实例
        mCameraDevice = CameraUtil.openCamera(
                mActivity, mCameraId, mHandler,
                mActivity.getCameraOpenErrorCallback());
        ...
    }

代码到了CameraUtil类里面,我们看下它搞啥玩意:

public static CameraManager.CameraProxy openCamera(
            Activity activity, final int cameraId,
            Handler handler, final CameraManager.CameraOpenErrorCallback cb) {
        try {
            throwIfCameraDisabled(activity);
            return CameraHolder.instance().open(handler, cameraId, cb);
        } catch (CameraDisabledException ex) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    cb.onCameraDisabled(cameraId);
                }
            });
        }
        return null;
    }

//代码到CameraHolder类的open方法
 public synchronized CameraProxy open(
            Handler handler, int cameraId,
            CameraManager.CameraOpenErrorCallback cb) {
        ...
                mCameraDevice = CameraManagerFactory
                        .getAndroidCameraManager().cameraOpen(handler, cameraId, cb);
            ...
        return mCameraDevice;
    }
//CameraManagerFactory类
public class CameraManagerFactory {

    private static AndroidCameraManagerImpl sAndroidCameraManager;

    /**
     * Returns the android camera implementation of {@link CameraManager}.
     *
     * @return The {@link CameraManager} to control the camera device.
     */
    public static synchronized CameraManager getAndroidCameraManager() {
        if (sAndroidCameraManager == null) {
            sAndroidCameraManager = new AndroidCameraManagerImpl();
        }
        return sAndroidCameraManager;
    }
}
//AndroidCameraManagerImpl 类的cameraOpen
@Override
    public CameraManager.CameraProxy cameraOpen(
        Handler handler, int cameraId, CameraOpenErrorCallback callback) {
        mCameraHandler.errorCbInstance = CameraOpenErrorCallbackForward
                .getNewInstance(handler, callback);
//在这里面使用mCameraHandler发送OPEN_CAMERA消息实例化一个Camera对象
        mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0, mCameraHandler.errorCbInstance)
                .sendToTarget();
        mCameraHandler.waitDone();
        if (mCamera != null) {
//将AndroidCameraProxyImpl代理类对象返回给调用者,调用者对象将通过它来操作Camera实例
            return new AndroidCameraProxyImpl();
        } else {
            return null;
        }
    }
//CameraHandler类,它是AndroidCameraManagerImpl 的内部类

@Override
        public void handleMessage(final Message msg) {
            try {
                switch (msg.what) {
                    case OPEN_CAMERA:
                        try {
//这里通过Java的反射机制来实例化Camrea
                            Method openMethod = Class.forName("android.hardware.Camera").getMethod(
                                    "openLegacy", int.class, int.class);
                            mCamera = (android.hardware.Camera) openMethod.invoke(
                                    null, msg.arg1, CAMERA_HAL_API_VERSION_1_0);
                        } catch (Exception e) {
                            /* Retry with open if openLegacy doesn't exist/fails */
                            Log.v(TAG, "openLegacy failed due to " + e.getMessage()
                                    + ", using open instead");
                            mCamera = android.hardware.Camera.open(msg.arg1);
                        }

                        if (mCamera != null) {
                            mParametersIsDirty = true;

                            // Get a instance of Camera.Parameters for later use.
                            if (mParamsToSet == null) {
                                mParamsToSet = mCamera.getParameters();
                            }
                        } else {
                            if (msg.obj != null) {
                                ((CameraOpenErrorCallback) msg.obj).onDeviceOpenFailure(msg.arg1);
                            }
                        }
                        return;

                    case RELEASE:
                        if (mCamera == null) {
                            return;
                        }
                        mCamera.release();
                        errorCbInstance = null;
                        mCamera = null;
                        return;

                    case RECONNECT:
                        mReconnectIOException = null;
                        try {
                            mCamera.reconnect();
                        } catch (IOException ex) {
                            mReconnectIOException = ex;
                        }
                        return;

                    ....
                }

代码跟踪到这里就要进入系统层的代码了,android.hardware.Camera的类在源码目录的位置/android/frameworks/base/core/java/android/hardware/Camera.java。

好了,文章到这里就先告一段落了,我们来终结一下:

App启动后代码的大致流程CameraApp-->CameraActivity.onCreate()-->CameraActivity.setModuleFromIndex()-->PhotoModule.init()-->启动OpenCameraThread线程-->打开相机openCamera()-->在AndroidCameraManagerImpl的CameraHandler里面通过反射机制实例化android.hardware.Camera

限于篇幅原因,我会在下一个博客讲解相机预览。

谢谢大家,希望这篇博客呢帮助到您,祝大家生活愉快,工作顺心。

你可能感兴趣的:(Android系统开发,笔记)