各位早上好,这次给大家带来的是Android9.0 Camera App的代码阅读,即是工作需要也是个人的笔记,帮助大家学习。
Android9.0 Camera App源代码的位置(/android/packages/apps/SnapdragonCamera),其他的Camera App在Android9.0中已经弃用了,我把源码导入到Android studio中让大家看看它的代码结构,如图:
这里着重要讲的是src里面的Java代码,导入到Android studio会有很多错误,博主一开始天真地以为可以在Android studio里面编译,但发现错误太多不现实,还是在源码里面编译吧,android studio就作为代码阅读工具用,大家也可以用source insight阅读,至于博主,两个都用。
好了,废话不多说我们开始阅读代码吧。
第一个问题:Carmera App是怎么启动的?
有Android App开发基础的同学就知道,Android App启动的时候第一个启动的就是Application.那么这个类在哪里,我们可以找到AndroidManifest.xml文件来看
看在这里,我们找到com.android.camera.app.CameraApp先
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
限于篇幅原因,我会在下一个博客讲解相机预览。
谢谢大家,希望这篇博客呢帮助到您,祝大家生活愉快,工作顺心。