Android 休眠状态对Camera预览的影响

http://blog.csdn.net/sevensundark/article/details/7433177

最近遇到的一个问题,app中有照相功能的预览画面,提供照相功能,在此画面打开的前提下,按关机键使机器进入休眠状态,然后再解除休眠回来,画面中的照相预览部分变成一片漆黑....可如果是app之间的切换(例如,Home键出去,再长按Home键回来)的话没有此问题。

首先打log对比休眠和普通切换App应用,系统做的事情有哪些区别: 休眠--状况A    切换App--状况B

画面打开:

    onCreate->onRestoreInstanceState->onStart->onResume->surfaceCreated->surfaceChanged->surfaceChanged  (surfaceChanged会执行两遍,还没研究为何)

状况A:

   1.进入休眠:onSaveInstanceState->onPause

   2.休眠解除:onResume

状况B:

  1.切出:onSaveInstanceState->onPause->surfaceDestroyed->onStop

  2.切回:onRestart->onStart->onResume->surfaceCreated->surfaceChanged

可以发现,休眠与解除休眠并没有像App切换那样做那么多事,surfaceDestroyed和surfaceChanged都没执行,代码中照相预览需要的Camera对象在surfaceDestroyed中进行释放,在surfaceCreated中进行实例化...

问题集中在上面两种变化状态都会执行的onPause方法里了,果然,onPause里也有对Camera对象进行释放的操作...

原因明了: 进入休眠状态时,执行了camera对象的释放,却在解除休眠状态时没有能执行surfaceCreated进行camera对象的实例化。

于是,删除onpause中释放camera对象的代码,大功告成......

不过,中间试验中发现个有趣的现象,预览用到的控件SurfaceView,取到这个对象,设置它的显示属性能够唤出surfaceDestroyed和surfaceCreated方法的执行。

在onPause中调用setVisibility(View.INVISIBLE)唤出surfaceDestroyed的执行,再在onResume中调用setVisibility(View.VISIBLE)唤出surfaceCreated的执行,同样解决问题。

为啥显示属性会触发到surfaceDestroyed和surfaceCreated,参考了一下源码,大概知道个所以然....

SurfaceView重写了父类(View)的setVisibility方法:

[java] view
plain
copyprint?

  1. @Override  
  2. public void setVisibility(int visibility) {  
  3.     super.setVisibility(visibility);  
  4.     mViewVisibility = visibility == VISIBLE;  
  5.     mRequestedVisible = mWindowVisibility && mViewVisibility;  
  6.     updateWindow(false, false);  
  7. }  

这里设置几个全局boolean变量,例如调用setVisibility(View.INVISIBLE)的时候,mViewVisibility和mRequestedVisible都被赋为false,然后调用updateWindow方法:

[java] view
plain
copyprint?

  1. private void updateWindow(boolean force, boolean redrawNeeded) {  
  2.           
  3.         ......  
  4.           
  5.         final boolean visibleChanged = mVisible != mRequestedVisible  
  6.                 || mNewSurfaceNeeded;  
  7.         final boolean typeChanged = mType != mRequestedType;  
  8.         if (force || creating || formatChanged || sizeChanged || visibleChanged  
  9.             || typeChanged || mLeft != mLocation[0] || mTop != mLocation[1]  
  10.             || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {  
  11.   
  12.             ......  
  13.               
  14.             try {  
  15.                 final boolean visible = mVisible = mRequestedVisible;  
  16.                   
  17.                 ......  
  18.   
  19.                 if (visibleChanged && (!visible || mNewSurfaceNeeded)) {  
  20.                     reportSurfaceDestroyed();  
  21.                 }  
  22.                   
  23.                 ......  
  24.   
  25.                 try {  
  26.                       
  27.                     ......  
  28.   
  29.                     if (visible) {  
  30.                         mDestroyReportNeeded = true;  
  31.   
  32.                         if (visibleChanged) {  
  33.                             mIsCreating = true;  
  34.                             for (SurfaceHolder.Callback c : callbacks) {  
  35.                                 c.surfaceCreated(mSurfaceHolder);  
  36.                             }  
  37.                         }  
  38.                     } else {  
  39.                         ......  
  40.                     }  
  41.                 } finally {  
  42.                     ......  
  43.                 }  
  44.             } catch (RemoteException ex) {  
  45.             }  
  46.             ......  
  47.         }  

去除了多余不需要关心的代码,主要的代码如上。根据前面setVisibility方法里boolean变量的值,能推断出几个关键分歧判断变量的值。

setVisibility(View.INVISIBLE)的场合:

    mVisible->ture   mViewVisibility->false    mRequestedVisible->false    visibleChanged->true    visible->false    于是reportSurfaceDestroyed执行,surfaceCreated不执行

setVisibility(View.VISIBLE)的场合:

    mVisible->false   mViewVisibility->true    mRequestedVisible->true    visibleChanged->true    visible->true    于是reportSurfaceDestroyed不执行,surfaceCreated执行

源码才是王道.......

时间: 2024-11-03 22:01:26

Android 休眠状态对Camera预览的影响的相关文章

请教关于android camera 预览显示方向的一个问题。

问题描述 请教关于android camera 预览显示方向的一个问题. 请教关于android camera 预览显示方向的一个问题:有什么方法能够在android 1.6以上的设备都可以设置预览显示方向? 解决方案 大多数的相机程序都使用横向拍照,这也是摄像头传感器的自然方向.但是这并不影响您在竖屏的时候拍照,设备的方向信息会存储到图片的EXIF信息中.可以通过函数 setCameraDisplayOrientation() 来改变预览的显示方向而不影响图片的保存数据.然而,在API lev

关于Android 4.4相机预览、录像花屏的问题的解决方法_Android

系统: lc android4.4 在做前后摄像头录像的时候,发现会出现花屏的时候,但不是必现,可能会在某一次重启之后会出现,而且出现之后会处于必现状态,除非再一次重启. 百度了很多解决方法,什么通过设置camera.unlock之类的,都是无法解决的,后面不断尝试,解决方法如下: 设置预览分辨率: Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(width, height); 注意

关于Android 4.4相机预览、录像花屏的问题的解决方法

系统: lc android4.4 在做前后摄像头录像的时候,发现会出现花屏的时候,但不是必现,可能会在某一次重启之后会出现,而且出现之后会处于必现状态,除非再一次重启. 百度了很多解决方法,什么通过设置camera.unlock之类的,都是无法解决的,后面不断尝试,解决方法如下: 设置预览分辨率: Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(width, height); 注意

解决Eclipse创建android项目无法正常预览布局文件问题的方法_Android

一.问题描述 今天使用SDK Manager将Android SDK的版本更新到了Android 5.1的版本,eclipse创建android项目时,预览activity_main.xml文件时提示:This version of the rendering library is more recent than your version of ADT plug-in. Please update ADT plug-in,导致无法正常预览布局文件,现象如下图所示: 上网查了一下原因,问题根源:

Android 实时视频采集—Cameara预览采集

http://www.cnblogs.com/skyseraph/archive/2012/03/26/2418665.html 1 概述 通过Android Camera拍摄预览中设置setPreviewCallback实现onPreviewFrame接口,实时截取每一帧视频流数据 2 知识点 ① Android Camera使用: 参考 Refs/Related 0-4 Camera 支持格式 拍照流程 ② Android SurfaceView使用: 参考 Refs/Related 5-1

Android 5.0 开发者预览版隐藏Flappy Bird克隆

在发布Android 5.0 Lollipop之后, Google发布了开发者预览版更新,加入了一些用户以后将会在正式版本中使用到的新功能,它还隐藏了一个至今最大的Android彩蛋--一个可玩的Flappy Bird克隆,用机器人和棒棒糖替换了Flappy Bird中的鸟和水管.彩蛋隐藏在设置下的"关于"选项内,游戏相比其它Flappy Bird克隆要简单,主要的区别是当玩家死掉重生后游戏偶尔会相反的方向滚入. 文章转载自 开源中国社区 [http://www.oschina.net

Android编程中调用Camera时预览画面有旋转问题的解决方法_Android

本文实例讲述了Android编程中调用Camera时预览画面有旋转问题的解决方法.分享给大家供大家参考,具体如下: 在调用Camera写应用的时候,前后摄像头的情况有时候是不一样的.有时候,明明后摄像头没有问题,而调用到前摄像头时,却倒转了180°,或者其他角度,百思不得其解.在查看了Android源码之后,发现它的解决办法很是好,接下来贴个源码,以备日后查看. public static int getDisplayRotation(Activity activity) { int rotat

Android:魅族Flyme OS 3摄像头无法预览的问题

错误代码: 12-12 14:28:34.692: E/AndroidRuntime(1524): java.lang.RuntimeException: startPreview failed 12-12 14:28:34.692: E/AndroidRuntime(1524): at android.hardware.Camera.startPreview(Native Method) 12-12 14:28:34.692: E/AndroidRuntime(1524): at com.nm

Firefox OS 2.5 开发者预览版是个 Android APP

Firefox OS 发布已经很长时间了,Firefox OS 是基于 Linux 系统,但是 Mozilla 的 R&D 团队正在努力尝试把 Firefox OS 移植到其他操作系统,可以在更多设备上使用.Firefox OS 2.5 提供了 Android 版本的开发者预览. Firefox移动操作系统前身为Mozilla的Boot to Gecko项目,其中的电话.短信.游戏等一切功能均是HTML5应用.没有所谓的"原生应用",游戏也多是HTML5应用,操作性能强悍,在系