驍龍相機是高通開發的一個測試系統攝像頭的demo,代碼完善,功能強大。可以配合Camera驅動進行功能聯調。
很多邏輯代碼在CaptureModule.java里。
CaptureModule有8000多行,包羅萬象。
涉及到界面顯示要結合CaptureUI.java? 一起來實現。
CaptureActivity持有了?CaptureModule 和 CaptureUI 。
以上是主要的引用關系。
CameraActivity 中調用了以下代碼
case ModuleSwitcher.CAPTURE_MODULE_INDEX:if(mCaptureModule == null) {mCaptureModule = new CaptureModule();//核心代碼!!!mCaptureModule.init(this, mCameraCaptureModuleRootView);} else {mCaptureModule.reinit();}mCurrentModule = mCaptureModule;mCameraCaptureModuleRootView.setVisibility(View.VISIBLE);Log.e("CameraActity"," setModuleFromIndex =================== CAPTURE_MODULE_INDEX");break;
?CaptureModule 里初始化代碼:
@Overridepublic void init(CameraActivity activity, View parent) {mActivity = activity;mRootView = parent;mSettingsManager = SettingsManager.getInstance();mSettingsManager.createCaptureModule(this);mSettingsManager.registerListener(this);if (mSettingsManager.mIsHasOneCamera) {CURRENT_ID = 0;} else {if (isBackCameraId()) {CURRENT_ID = BACK_MODE;} else {CURRENT_ID = FRONT_MODE;}}mSettingsManager.init();mFirstPreviewLoaded = false;Log.d(TAG, "init");for (int i = 0; i < MAX_NUM_CAM; i++) {mCameraOpened[i] = false;mTakingPicture[i] = false;}for (int i = 0; i < MAX_NUM_CAM; i++) {mState[i] = STATE_PREVIEW;}SceneModule module;for (int i = 0; i < mSelectableModes.length + 2; i++) {module = new SceneModule();module.mode = CameraMode.values()[i];mSceneCameraIds.add(module);}mPostProcessor = new PostProcessor(mActivity, this);mFrameProcessor = new FrameProcessor(mActivity, this);mContentResolver = mActivity.getContentResolver();initModeByIntent();initCameraIds();mUI = new CaptureUI(activity, this, parent);mUI.initializeControlByIntent();mFocusStateListener = new FocusStateListener(mUI);mLocationManager = new LocationManager(mActivity, this);}
通過以下代碼初始化CaptureUI
mUI = new CaptureUI(activity, this, parent);mUI.initializeControlByIntent();
介紹一個核心操作來,了解是如何切換拍照模式的。
首先,通過CaptureUI ,來對組件賦予監聽回調。
mFlashButton = (FlashToggleButton) mRootView.findViewById(R.id.flash_button);mModeSelectLayout = (RecyclerView) mRootView.findViewById(R.id.mode_select_layout);mModeSelectLayout.setLayoutManager(new LinearLayoutManager(mActivity,LinearLayoutManager.HORIZONTAL, false));mCameraModeAdapter = new Camera2ModeAdapter(mModule.getCameraModeList());//設置單擊回調 mCameraModeAdapter.setOnItemClickListener(mModule.getModeItemClickListener());mModeSelectLayout.setAdapter(mCameraModeAdapter);mSettingsIcon = (ImageView) mRootView.findViewById(R.id.settings);mSettingsIcon.setImageResource(R.drawable.settings);mSettingsIcon.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {openSettingsMenu();}});
對應CaptureModule的處理。
public OnItemClickListener getModeItemClickListener() {return new OnItemClickListener() {@Overridepublic int onItemClick(int mode) {if (showLog) Log.e(TAG, "mode >>> " + mode);if (!getCameraModeSwitcherAllowed()) {return -1;}if (mode == CameraMode.VIDEO.ordinal()) {videoCameraId = -1;videoType = VIDEO_DEFAULT;} else {if (mode == CameraMode.MACRO.ordinal() || mode == CameraMode.NIGHT.ordinal()) {videoCameraId = -1;videoType = -1;}}return selectCameraMode(mode);}};}
CaptureModule 核心代碼處理:
public int selectCameraMode(int mode) {if (showLog) Log.e("CaptureModule", " mode:: ============== " + mode);if (showLog)Log.e("CaptureModule", " mCurrentSceneMode.mode:: =================== " + mCurrentSceneMode.mode);for (SceneModule sceneModule : mSceneCameraIds) {if (showLog) Log.e(TAG, " secenmode:: >> " + sceneModule.mode);}if (showLog)Log.e("CaptureModule", " mSceneCameraIds.get(mode).mode:: =================== " + mSceneCameraIds.get(mode).mode);if (showLog) Log.e("CaptureModule", " videoType:: =================== " + videoType);if (showLog)Log.e("CaptureModule", " videoCameraId:: =================== " + videoCameraId);showCameraDevice();String value = mSettingsManager.getValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE);boolean post = false;if (mode == CameraMode.VIDEO.ordinal()) {videoType = VIDEO_DEFAULT;videoCameraId = 0;} else if (mode == CameraMode.MACRO.ordinal()) {if (value != null && value.equals("front")) {post = true;if (!isBackCamera()) {mUI.performCameraSwitchClick();}}} else if (mode == CameraMode.DEFAULT.ordinal()) {videoType = -1;videoCameraId = -1;} else if (mode == CameraMode.NIGHT.ordinal()) {if (value != null && value.equals("front")) {if (!isBackCamera()) {post = true;mUI.performCameraSwitchClick();}}if (showLog)Log.e("xxx", " mPreviewRequestBuilder.length ===========> " + mPreviewRequestBuilder.length);if (showLog)Log.e("xxx", " mPreviewRequestBuilder.length ===========> " + mPreviewRequestBuilder.length);} else if (mode == CameraMode.PRO_MODE.ordinal()) {
// if (value != null && value.equals("front")) {
// if (!isBackCamera()) {
// post = true;
// mUI.performCameraSwitchClick();
// }
// }} else if (mode == CameraMode.HFR.ordinal()) {if (value != null && value.equals("front")) {if (!isBackCamera()) {post = true;mUI.performCameraSwitchClick();}}}if (showLog)Log.e("CaptureModule", " mode2:: ============== " + mode);if (showLog)Log.e("CaptureModule", " mCurrentSceneMode.mode2 :: =================== " + mCurrentSceneMode.mode);if (showLog)Log.e("CaptureModule", " mSceneCameraIds.get(mode).mode2 :: =================== " + mSceneCameraIds.get(mode).mode);showCameraDevice();nmode = mode;if (post) {mHandler.postDelayed(new Runnable() {@Overridepublic void run() {selectModle(nmode);}}, 1000);} else {selectModle(mode);}return 1;}
以上經過定制后的代碼。代碼邏輯更加復雜。因為要支持,夜視和微距攝像頭效果。還要支持前攝。
再調用selectModle方法
selectModle(int mode)
private int selectModle(int mode) {
// if (!isVideoModel) {
// if (mCurrentSceneMode.mode == mSceneCameraIds.get(mode).mode) {
// return -1;
// }
// }showCameraDevice();setCameraModeSwitcherAllowed(false);setNextSceneMode(mode);SceneModule nextSceneMode = mSceneCameraIds.get(mode);String value = mSettingsManager.getValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE);if (showLog)Log.e(TAG, " =============== current Mode is ::: " + mCurrentSceneMode.mode.ordinal());if (value != null && value.equals("front") &&(nextSceneMode.mode == CameraMode.RTB|| nextSceneMode.mode == CameraMode.SAT|| nextSceneMode.mode == CameraMode.PRO_MODE)) {if (showLog)Log.e(TAG, " selectModle begin set value KEY_FRONT_REAR_SWITCHER_VALUE rear ========== mode:: " + mode);mSettingsManager.setValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE, "rear");} else {if (showLog) Log.e(TAG, " restartAll ========== mode:: " + mode);restartAll();}updateZoomSeekBarVisible();return 1;}
再調用?restartAll方法
public void restartAll() {showCameraDevice();int nextCameraId = getNextScreneModeId(mNextModeIndex);CURRENT_ID = getMainCameraId();Log.d(TAG, "restart all CURRENT_ID :" + CURRENT_ID + " nextCameraId :" + nextCameraId);if (CURRENT_ID == nextCameraId && mCameraDevice[nextCameraId] != null) {mIsCloseCamera = false;} else {mIsCloseCamera = true;}SceneModule nextSceneModule = mSceneCameraIds.get(mNextModeIndex);if (nextSceneModule.mode == CameraMode.DEFAULT|| nextSceneModule.mode == CameraMode.PRO_MODE|| nextSceneModule.mode == CameraMode.HFR) {mIsCloseCamera = true;}if (mCameraDevice[nextCameraId] == null) {if (showLog) Log.e(TAG, " mCameraDevice[nextCameraId] is null " + nextCameraId);} else {if (showLog) Log.e(TAG, " mCameraDevice[nextCameraId] is not null " + nextCameraId);}
在restartAll中執行各種Camera的初始化操作。首先要關閉原來的攝像頭資源,再打開新的攝像頭資源。各種操作都封裝在以下幾個方法。
onPauseBeforeSuper(); if (showLog) Log.e(TAG, " do onPauseBeforeSuper"); onPauseAfterSuper(false); if (showLog) Log.e(TAG, " do onPauseAfterSuper false"); reinitSceneMode(); if (showLog) Log.e(TAG, " do reinitSceneMode "); onResumeBeforeSuper(true); if (showLog) Log.e(TAG, " do onResumeBeforeSuper "); onResumeAfterSuper(true); if (showLog) Log.e(TAG, " do onResumeAfterSuper "); setRefocusLastTaken(false); if (showLog) Log.e(TAG, " do setRefocusLastTaken ");
打開攝像頭的操作。
onResumeAfterSuper 方法里的
if (mIsCloseCamera) {Message msg = Message.obtain();msg.what = OPEN_CAMERA;msg.arg1 = mCurrentSceneMode.getCurrentId();Log.d(TAG, "open is " + msg.arg1);if (mCameraHandler != null) {mCameraHandler.sendMessage(msg);}}
對應Handle的操作
private class MyCameraHandler extends Handler {public MyCameraHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {int id = msg.arg1;switch (msg.what) {case OPEN_CAMERA:openCamera(id);break;case CANCEL_TOUCH_FOCUS:cancelTouchFocus(id);break;}}}
執行openCamra操作:
private void openCamera(int id) {if (mPaused) {return;}if (showLog) Log.e(TAG, "openCamera 1111 " + id);CameraManager manager;try {manager = (CameraManager) mActivity.getSystemService(Context.CAMERA_SERVICE);mCameraId[id] = manager.getCameraIdList()[id];if (!mCameraOpenCloseLock.tryAcquire(5000, TimeUnit.MILLISECONDS)) {Log.d(TAG, "Time out waiting to lock camera opening.");throw new RuntimeException("Time out waiting to lock camera opening");}manager.openCamera(mCameraId[id], mStateCallback, mCameraHandler);} catch (CameraAccessException e) {e.printStackTrace();if (showLog) Log.d(TAG, "openCamera CameraAccessException 2222" + id);} catch (InterruptedException e) {e.printStackTrace();if (showLog) Log.d(TAG, "openCamera InterruptedException 3333 " + id);} catch (Exception e) {e.printStackTrace();if (showLog) Log.d(TAG, "openCamera Exception 44444 " + id);}if (showLog) Log.d(TAG, "openCamera end 55555 " + id);}
回調mStateCallback 操作。
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {@Overridepublic void onOpened(CameraDevice cameraDevice) {int id = Integer.parseInt(cameraDevice.getId());Log.d(TAG, "onOpened " + id);mCameraOpenCloseLock.release();if (mPaused) {return;}showCameraDevice();if (showLog)Log.e(TAG, "mStateCallback onOpened ========== id:: " + id);mCameraDevice[id] = cameraDevice;mCameraOpened[id] = true;if (isBackCamera() && getCameraMode() == DUAL_MODE && id == BAYER_ID) {Message msg = mCameraHandler.obtainMessage(OPEN_CAMERA, MONO_ID, 0);mCameraHandler.sendMessage(msg);} else {mCamerasOpened = true;if (showLog)Log.e(TAG, "mStateCallback onOpened ========== mCamerasOpened:: " + mCamerasOpened);mActivity.runOnUiThread(new Runnable() {@Overridepublic void run() {if (showLog)Log.e(TAG, "mStateCallback onOpened ========== mUI.onCameraOpened:: ");mUI.onCameraOpened(mCurrentSceneMode.getCurrentId());if (showLog)Log.e(TAG, "mStateCallback onOpened ========== mUI.onCameraOpened:: end ");}});showCameraDevice();createSessions();}}
注意?mCameraDevice[id] = cameraDevice; 和?? mCameraOpened[id] = true;? 有幾個攝像頭就有幾個mCameraDevice。id就是CameraId,一般就是其下標。
同樣會有一個非常重要的函數?createSessions() ,有了 CameraDevice就要創建 CaptureSeesion。
private void createSessions() {if (PersistUtil.isTraceEnable())Trace.beginSection("createSessions");if (mPaused || !mCamerasOpened || mTempHoldVideoInVideoIntent) return;int cameraId = mCurrentSceneMode.getCurrentId();if (showLog)Log.e(TAG, "createSessions : Current SceneMode is ==== " + mCurrentSceneMode.mode);Log.e(TAG, "createSessions : Current cameraId is ===== " + cameraId);showCameraDevice();switch (mCurrentSceneMode.mode) {case VIDEO:case VIDEO_NIGHT:case VIDEO_MACRO:case NIGHT:createSessionForVideo(cameraId);break;case HFR:if (!HFR_RATE.equals("")) {mSettingsManager.setValue(SettingsManager.KEY_VIDEO_HIGH_FRAME_RATE, HFR_RATE);}createSessionForVideo(cameraId);break;default:createSession(cameraId);}if (PersistUtil.isTraceEnable())Trace.endSection();}
對應的會執行2個方法,一個是創建Camera的Session? createSession(cameraId)? 一個是創建Video的Session??createSessionForVideo(cameraId)
createSession()
if (mChosenImageFormat == ImageFormat.YUV_420_888 || mChosenImageFormat == ImageFormat.PRIVATE) {if (mPostProcessor.isZSLEnabled()) {mPreviewRequestBuilder[id].addTarget(mImageReader[id].getSurface());list.add(mPostProcessor.getZSLReprocessImageReader().getSurface());if (mSaveRaw) {mPreviewRequestBuilder[id].addTarget(mRawImageReader[id].getSurface());}mCameraDevice[id].createReprocessableCaptureSession(new InputConfiguration(mImageReader[id].getWidth(),mImageReader[id].getHeight(), mImageReader[id].getImageFormat()), list, captureSessionCallback, mCameraHandler);} else {if (mSettingsManager.isHeifWriterEncoding() && outputConfigurations != null) {mCameraDevice[id].createCaptureSessionByOutputConfigurations(outputConfigurations,captureSessionCallback, mCameraHandler);} else {mCameraDevice[id].createCaptureSession(list, captureSessionCallback, mCameraHandler);}}} else {outputConfigurations = null;if (ApiHelper.isAndroidPOrHigher() && outputConfigurations != null) {Log.i(TAG, "list size:" + list.size());Log.i(TAG, "create session 111 ");createCameraSessionWithSessionConfiguration(id, outputConfigurations,captureSessionCallback, mCameraHandler, mPreviewRequestBuilder[id]);// mCameraDevice[id].createCaptureSession(list, captureSessionCallback, mCameraHandler);} else {Log.i(TAG, "create session 222 ");mCameraDevice[id].createCaptureSession(list, captureSessionCallback, mCameraHandler);}
?captureSessionCallback 的操作
CameraCaptureSession.StateCallback captureSessionCallback =new CameraCaptureSession.StateCallback() {@Overridepublic void onConfigured(CameraCaptureSession cameraCaptureSession) {if (mPaused || null == mCameraDevice[id] ||cameraCaptureSession == null) {return;}Log.i(TAG, "cameracapturesession - onConfigured " + id);setCameraModeSwitcherAllowed(true);// When the session is ready, we start displaying the preview.mCaptureSession[id] = cameraCaptureSession;if (id == getMainCameraId()) {mCurrentSession = cameraCaptureSession;}initializePreviewConfiguration(id);setDisplayOrientation();updateFaceDetection();mFirstPreviewLoaded = false;try {if (isBackCamera() && getCameraMode() == DUAL_MODE) {linkBayerMono(id);mIsLinked = true;}// Finally, we start displaying the camera preview.// for cases where we are in dual mode with mono preview off,// don't set repeating request for monoif (mCaptureSession[id] == null) {return;}
// if (id == NIGHT_CAMRA_ID) { //Night模式
// mPreviewRequestBuilder[id].set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
// }if (id == MONO_ID && !canStartMonoPreview()&& getCameraMode() == DUAL_MODE) {mCaptureSession[id].capture(mPreviewRequestBuilder[id].build(), mCaptureCallback, mCameraHandler);} else {if (id == NIGHT_CAMRA_ID) { //Night模式mPreviewRequestBuilder[id].set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
// mPreviewRequestBuilder[id].set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);Log.d(TAG, "createSession : mPreviewRequestBuilder FLASH_MODE_TORCH ===== ");}mCaptureSession[id].setRepeatingRequest(mPreviewRequestBuilder[id].build(), mCaptureCallback, mCameraHandler);}if (mIntentMode == INTENT_MODE_STILL_IMAGE_CAMERA &&mIsVoiceTakePhote) {mHandler.sendEmptyMessageDelayed(VOICE_INTERACTION_CAPTURE, 500);}if (isClearSightOn()) {ClearSightImageProcessor.getInstance().onCaptureSessionConfigured(id == BAYER_ID, cameraCaptureSession);} else if (mChosenImageFormat == ImageFormat.PRIVATE && id == getMainCameraId()) {mPostProcessor.onSessionConfigured(mCameraDevice[id], mCaptureSession[id]);}} catch (CameraAccessException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}mCurrentSessionClosed = false;}@Overridepublic void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {if (showLog)Log.e(TAG, "cameracapturesession - onConfigureFailed " + id);setCameraModeSwitcherAllowed(true);if (mActivity.isFinishing()) {return;}
// Toast.makeText(mActivity, "Camera Initialization Failed",
// Toast.LENGTH_SHORT).show();}@Overridepublic void onClosed(CameraCaptureSession session) {Log.d(TAG, "cameracapturesession - onClosed");setCameraModeSwitcherAllowed(true);}};
createSessionForVideo()
if (showLog)Log.e(TAG, "createSessionForVideo 66666666666666 ");if (isHighSpeedRateCapture()) {int optionMode = isSSMEnabled() ? STREAM_CONFIG_SSM : SESSION_HIGH_SPEED;if (showLog)Log.e("TAG", " buildConstrainedCameraSession in ");buildConstrainedCameraSession(mCameraDevice[cameraId], optionMode,surfaces, mSessionListener, mCameraHandler, mVideoRecordRequestBuilder);if (showLog)Log.e(TAG, "createSessionForVideo 77777777777777777");} else {if (showLog)Log.e("TAG", " configureCameraSessionWithParameters in cameraId :: " + cameraId);configureCameraSessionWithParameters(cameraId, surfaces,mSessionListener, mCameraHandler, mVideoRecordRequestBuilder);if (showLog)Log.e(TAG, "createSessionForVideo 888888888888");}
創建CameraSession和VideoSession的主要區別。
CameraSession 使用了 mVideoRecordRequestBuilder 和 mPreviewRequestBuilder。 VideoSession 使用了 mVideoPreviewSurface 和 mMediaRecorderSurface。
CameraSession 通過拍照操作,來使用ImageReader獲取圖片數據。對應CameraSession有ImageReader實現的地方。
mCurrentSession.setRepeatingRequest(mVideoRecordRequestBuilder.build(),mCaptureCallback, mCameraHandler);
執行以上操作后,就可以預覽看到的內容了。
對應的,還有關閉Camera的操作。
closeCamera()
/*** Closes the current {@link CameraDevice}.*/private void closeCamera() {Log.d(TAG, "closeCamera ============== begin");closeProcessors();/* no need to set this in the callback and handle asynchronously. This is the samereason as why we release the semaphore here, not in camera close callback functionas we don't have to protect the case where camera open() gets called during cameraclose(). The low level framework/HAL handles the synchronization for open()happens after close() */try {// Close camera starting with AUX firstfor (int i = MAX_NUM_CAM - 1; i >= 0; i--) {if (null != mCameraDevice[i]) {try {if (!mCameraOpenCloseLock.tryAcquire(2000, TimeUnit.MILLISECONDS)) {Log.d(TAG, "Time out waiting to lock camera closing.");
// throw new RuntimeException("Time out waiting to lock camera closing");}} catch (Exception e) {mCameraOpenCloseLock.release();e.printStackTrace();}Log.d(TAG, "Closing camera: " + mCameraDevice[i].getId());// session was closed here if intentMode is INTENT_MODE_VIDEOif (mIntentMode != INTENT_MODE_VIDEO) {try {if (isAbortCapturesEnable() && mCaptureSession[i] != null) {mCaptureSession[i].abortCaptures();Log.d(TAG, "Closing camera call abortCaptures ");}if (isSendRequestAfterFlushEnable() && mCaptureSession[i] != null) {Log.v(TAG, "Closing camera call setRepeatingRequest");mCaptureSession[i].setRepeatingRequest(mPreviewRequestBuilder[i].build(),mCaptureCallback, mCameraHandler);}} catch (IllegalStateException | CameraAccessException e) {e.printStackTrace();}}mCameraDevice[i].close();mCameraDevice[i] = null;mCameraOpened[i] = false;mCaptureSession[i] = null;}}mIsLinked = false;if (null != mMediaRecorder) {mMediaRecorder.release();mMediaRecorder = null;}} catch (RuntimeException e) {mCameraOpenCloseLock.release();
// throw new RuntimeException("Interrupted while trying to lock camera closing.", e);e.printStackTrace();} catch (Exception e) {e.printStackTrace();} finally {mCurrentSessionClosed = true;mCameraOpenCloseLock.release();}Log.d(TAG, "closeCamera ============== end");}
closeImageReader()的操作
private void closeImageReader() {for (int i = MAX_NUM_CAM - 1; i >= 0; i--) {if (null != mImageReader[i]) {mImageReader[i].close();mImageReader[i] = null;}if (null != mRawImageReader[i]) {mRawImageReader[i].close();mRawImageReader[i] = null;}}for (int i = mYUVCount - 1; i >= 0; i--) {if (null != mYUVImageReader[i]) {mYUVImageReader[i].close();mYUVImageReader[i] = null;}}if (null != mVideoSnapshotImageReader) {mVideoSnapshotImageReader.close();mVideoSnapshotImageReader = null;}}
closeProcessors()
private void closeProcessors() {if (mPostProcessor != null) {mPostProcessor.onClose();}if (mFrameProcessor != null) {mFrameProcessor.onClose();}}
closeSessions()
private void closeSessions() {for (int i = MAX_NUM_CAM - 1; i >= 0; i--) {if (null != mCaptureSession[i]) {if (mCamerasOpened) {try {if (mCurrentSession instanceof CameraConstrainedHighSpeedCaptureSession) {List requestList = ((CameraConstrainedHighSpeedCaptureSession)mCurrentSession).createHighSpeedRequestList(mVideoRecordRequestBuilder.build());mCurrentSession.captureBurst(requestList, null, mCameraHandler);} else {mCaptureSession[i].capture(mPreviewRequestBuilder[i].build(), null,mCameraHandler);}} catch (CameraAccessException e) {e.printStackTrace();} catch (IllegalStateException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();}}mCaptureSession[i].close();mCaptureSession[i] = null;}}}
以上是Camera的初始化流程,很復雜。這里單純的是CaptureModule的邏輯。其中還要涉及到
CaptureUI的邏輯交互。
其中主要調用 showRelatedIcons(CaptureModule.CameraMode mode),根據顯示模式顯示不同的界面。
public void showRelatedIcons(CaptureModule.CameraMode mode) {//common settingsmShutterButton.setVisibility(View.VISIBLE);mFrontBackSwitcher.setVisibility(View.VISIBLE);photoVideoSwitcher.setVisibility(View.INVISIBLE);txt_macro_advice.setVisibility(View.INVISIBLE);mMakeupButton.setVisibility(View.INVISIBLE);mSceneModeSwitcher.setVisibility(View.INVISIBLE);//settings for each modeswitch (mode) {case DEFAULT:mFilterModeSwitcher.setVisibility(View.VISIBLE);mSceneModeSwitcher.setVisibility(View.VISIBLE);mVideoButton.setVisibility(View.INVISIBLE);mMuteButton.setVisibility(View.INVISIBLE);mPauseButton.setVisibility(View.INVISIBLE);break;case RTB:case SAT:mFilterModeSwitcher.setVisibility(View.VISIBLE);mSceneModeSwitcher.setVisibility(View.VISIBLE);mVideoButton.setVisibility(View.INVISIBLE);mFlashButton.setVisibility(View.INVISIBLE);mMuteButton.setVisibility(View.INVISIBLE);mPauseButton.setVisibility(View.INVISIBLE);if (!DEV_LEVEL_ALL) {mFrontBackSwitcher.setVisibility(View.INVISIBLE);}break;case VIDEO:case HFR:mFrontBackSwitcher.setVisibility(View.VISIBLE);photoVideoSwitcher.setVisibility(View.INVISIBLE);mVideoButton.setVisibility(View.VISIBLE);mFilterModeSwitcher.setVisibility(View.VISIBLE);if (mModule.isBackCamera()) {mFlashButton.setVisibility(View.INVISIBLE);} else {mFlashButton.setVisibility(View.VISIBLE);}mShutterButton.setVisibility(View.INVISIBLE);break;case PRO_MODE:mFilterModeSwitcher.setVisibility(View.INVISIBLE);mVideoButton.setVisibility(View.INVISIBLE);mFrontBackSwitcher.setVisibility(View.INVISIBLE);mMuteButton.setVisibility(View.INVISIBLE);mPauseButton.setVisibility(View.INVISIBLE);
// if (mModule.isBackCamera()) {
// mFlashButton.setVisibility(View.VISIBLE);
// } else {mFlashButton.setVisibility(View.INVISIBLE);
// }break;case MACRO:mFrontBackSwitcher.setVisibility(View.INVISIBLE);photoVideoSwitcher.setVisibility(View.VISIBLE);((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.video_switch);mVideoButton.setVisibility(View.INVISIBLE);mFilterModeSwitcher.setVisibility(View.INVISIBLE);txt_macro_advice.setVisibility(View.VISIBLE);break;case VIDEO_MACRO:mFrontBackSwitcher.setVisibility(View.INVISIBLE);photoVideoSwitcher.setVisibility(View.VISIBLE);((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.photo_switch);mVideoButton.setVisibility(View.VISIBLE);mFilterModeSwitcher.setVisibility(View.INVISIBLE);mShutterButton.setVisibility(View.INVISIBLE);txt_macro_advice.setVisibility(View.VISIBLE);break;case VIDEO_NIGHT:mFlashButton.setVisibility(View.VISIBLE);mFrontBackSwitcher.setVisibility(View.INVISIBLE);photoVideoSwitcher.setVisibility(View.VISIBLE);((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.photo_switch);mFilterModeSwitcher.setVisibility(View.INVISIBLE);mShutterButton.setVisibility(View.INVISIBLE);mVideoButton.setVisibility(View.VISIBLE);break;case NIGHT:mFlashButton.setVisibility(View.INVISIBLE);mFrontBackSwitcher.setVisibility(View.INVISIBLE);photoVideoSwitcher.setVisibility(View.VISIBLE);((RotateImageView) photoVideoSwitcher).setImageResource(R.drawable.video_switch);mVideoButton.setVisibility(View.INVISIBLE);mFilterModeSwitcher.setVisibility(View.INVISIBLE);break;default:break;}String value = mSettingsManager.getValue(SettingsManager.KEY_FRONT_REAR_SWITCHER_VALUE);if (value == null) {mFrontBackSwitcher.setVisibility(View.INVISIBLE);}if (mModule.getVideoType() == CaptureModule.VIDEO_DEFAULT || mModule.getCurrenCameraMode() == CaptureModule.CameraMode.HFR) {photoVideoSwitcher.setVisibility(View.INVISIBLE);if (mModule.getCurrenCameraMode() == CaptureModule.CameraMode.HFR) {if (mModule.isBackCamera()) {mFlashButton.setVisibility(View.VISIBLE);} else {mFlashButton.setVisibility(View.INVISIBLE);}}}if (mModule.mMFNREnable && mModule.getMainCameraId() == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT) {mFilterModeSwitcher.setVisibility(View.INVISIBLE);}}
源碼多讀,多多比較思考和跟蹤代碼的流程。
如何編譯 在SnapdragonCamera工程呢?
執行
source? ./build/envsetup.sh
執行
lunch
選擇正確的配置
在SnapdragonCamera工程下,執行 ,
mm
編譯即可。
執行
adb install -r? ../../../../SnapdragonCamera.apk
安裝即可。