Android -- Camera源码简析,启动流程
com.android.camera.Camera.java,主要的实现Activity,继承于ActivityBase。
ActivityBase
在ActivityBase中执行流程:
- onCreate中进行判断是否是平板;
- onResume中判断是否锁屏,锁屏&camera不存在时候,mOnResumePending置为true,否则置为false并执行doOnResume;
- onWindowFocusChanged中判断是否获取到焦点&mOnResumePending,满足的话执行doOnResume;
- 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;
我是天王盖地虎的分割线
Android -- Camera源码简析,启动流程的更多相关文章
- Flink源码阅读(一)——Flink on Yarn的Per-job模式源码简析
一.前言 个人感觉学习Flink其实最不应该错过的博文是Flink社区的博文系列,里面的文章是不会让人失望的.强烈安利:https://ververica.cn/developers-resource ...
- SpringMVC学习(一)——概念、流程图、源码简析
学习资料:开涛的<跟我学SpringMVC.pdf> 众所周知,springMVC是比较常用的web框架,通常整合spring使用.这里抛开spring,单纯的对springMVC做一下总 ...
- django-jwt token校验源码简析
一. jwt token校验源码简析 1.1 前言 之前使用jwt签发了token,里面的头部包含了加密的方式.是否有签名等,而载荷中包含用户名.用户主键.过期时间等信息,最后的签名还使用了摘要算法进 ...
- Appium Android Bootstrap源码分析之启动运行
通过前面的两篇文章<Appium Android Bootstrap源码分析之控件AndroidElement>和<Appium Android Bootstrap源码分析之命令解析 ...
- 0002 - Spring MVC 拦截器源码简析:拦截器加载与执行
1.概述 Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理.例如通过拦截器可以进行权限验证.记录请求信息的日 ...
- Python Web Flask源码解读(一)——启动流程
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...
- Flume-ng源码解析之启动流程
今天我们通过阅读Flume-NG的源码来看看Flume的整个启动流程,废话不多说,翠花,上源码!! 1 主类也是启动类 在这里我贴出Application中跟启动有关的方法,其他你们可以自己看源码,毕 ...
- AFNetworking源码简析
AFNetworking基本是苹果开发中网络请求库的标配,它是一个轻量级的网络库,专门针对iOS和OS X的网络应用设计,具有模块化的架构和丰富的APIs接口,功能强大并且使用简单,深受苹果应用开发人 ...
- SpringMVC源码解析-DispatcherServlet启动流程和初始化
在使用springmvc框架,会在web.xml文件配置一个DispatcherServlet,这正是web容器开始初始化,同时会在建立自己的上下文来持有SpringMVC的bean对象. 先从Dis ...
随机推荐
- scrapy爬虫,爬取图片
一.scrapy的安装: 本文基于Anacoda3, Anacoda2和3如何同时安装? 将Anacoda3安装在C:\ProgramData\Anaconda2\envs文件夹中即可. 如何用con ...
- windows下thrift的使用(C++)
thrift cpp环境搭建: 1. 安装boost_1_53_0,注意,使用vs2010版本时,使用二进制的boost安装版本,生成的lib有可能是,在后续操作会出问题.在源码目录中,运行boot ...
- BeautifulSoup与Xpath解析库总结
一.BeautifulSoup解析库 1.快速开始 html_doc = """ <html><head><title>The Dor ...
- 学好js,这些js函数概念一定要知道
函数创建方式 1.声明方式 例如:function consoleTip (){ console.log("tip!"); } 2.表达式方式 例如:var consoleTip ...
- md 添加 图片
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 1.在github上的仓库建立一个存放图片的文件夹,文件夹名字随意.如:img-fold ...
- 1316 文化之旅 2012年NOIP全国联赛普及组
题目描述 Description 有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家).不同的国 ...
- POJ 2987 Firing 网络流 最大权闭合图
http://poj.org/problem?id=2987 https://blog.csdn.net/u014686462/article/details/48533253 给一个闭合图,要求输出 ...
- Codeforces Round #357 (Div. 2) B. Economy Game 水题
B. Economy Game 题目连接: http://www.codeforces.com/contest/681/problem/B Description Kolya is developin ...
- Git_管理修改
现在,假定你已经完全掌握了暂存区的概念.下面,我们要讨论的就是,为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件. 你会问,什么是修改?比如你新增了一行,这就是一个修改 ...
- C#程序集系列08,设置程序集版本
区别一个程序集,不仅仅是程序集名称,还包括程序集版本.程序集公匙.程序集文化等,本篇体验通过界面和编码设置程序集版本. □ 通过Visual Studio设置程序集版本 →右键项目,选择"属 ...