PowerManager屏幕休眠断网与距离感应器P-Sensor

来源:互联网 发布:英语演讲主题 知乎 编辑:程序博客网 时间:2024/05/01 16:11

PowerManager屏幕休眠断网与距离感应器P-Sensor


PowerManager.java

1.  应用程序获取PowerManager服务, 我们可以这样书写:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);  



2.  goToSleep()方法, 这个方法可以强制我们的屏幕熄屏。我们可以这样调用:

     在上面拿到pm对象之后,这样调用 pm.goToSleep(SystemClock.uptimeMillis());


3.  setBacklightBrightness()方法,这个方法可以设置背光的亮度,从0-255 

三.  定时熄灭屏幕

有时屏幕休眠状态会造成断网,

那么这里,还可以介绍一个控制屏幕的方法就是PowerManager.WakeLock
顾名思义,WakeLock这个东西就是亮屏控制,这里说的亮屏,它定义了几种类型的亮屏。如下:
类型cpu屏幕键盘PARTIAL_WAKE_LOCKonoffoffSCREEN_DIM_WAKE_LOCKondimoffSCREEN_BRIGHT_WAKE_LOCKonBrightoffFULL_WAKE_LOCKonBrightBright

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);    
  2. PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG");    
  3. wakeLock.acquire();    


//做我们的工作,在这个阶段,我们的屏幕会持续点亮

//释放锁,屏幕熄灭。

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. wakeLock.release()  


那么这里我们也可以这样使用,就是多少时间后熄灭屏幕
首先点亮屏幕
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);    
  2. PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG");    
  3. wakeLock.acquire();    
  4. 然后  
  5. mTimeHandler.postDelayed(new Runnable(){  
  6.                 public void run(){  
  7.                     wakeLock.release();  
  8.                 }  
  9.             }, 10*1000);  


嗯,延迟10s后熄灭屏幕。。。。

那么,这里要注意的是acquire()和release()要成对调用哦!也就是说,你申请了亮屏,过段时间,你要是释放它。


P-Sensor,距离感应器,可以感应手机和人体距离。具体使用用途是在通话过程中打开P-Sensor时靠近脸时屏幕熄灭,第三方apk无法调用,只能系统开发调用

参考http://blog.csdn.net/wds1181977/article/details/18005665

    http://bbs.51cto.com/thread-1021568-1.html

Android4.2源码Phone的模块的P-Sensor的控制的类在DisplayPowerController.java

路径:framework/base/services/java/com/android/server/power/DisplayPowerController.java中的:


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private PowerManager.WakeLock mProximityWakeLock;  
  2. roximityWakeLock =  pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, LOG_TAG);  



打开P-Sensor(正确的说法是获得锁)

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. if (!mProximityWakeLock.isHeld()) {  
  2.                         if (DBG) Log.d(LOG_TAG, "updateProximitySensorMode: acquiring...");  
  3.                         mProximityWakeLock.acquire();  
  4.                     }  



释放P-Sensor

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. if (mProximityWakeLock.isHeld()) {  
  2.      mProximityWakeLock.release(flags)  
  3. }  


这个mProximityWakeLock.acquire();和mProximityWakeLock.release(flags);只是申请这个锁,和释放这个锁,防止其他的调用其中mProximityWakeLock.acquire();会辗转调用到PowerManagerService.java的enableProximityLockLocked()方法,顾名思义,这个方法是打开P-Sensor,是的!这个方法会去判断当前手机有没有P-Sensor,如果有的话,就会去向SensorManager注册一个P-Sensor监听器,那么当P-Sensor检测到手机和人体距离发生改变时,就会调用我们PowerManagerService.java的监听器.同样,当电话挂断时,电话模块会去调用mProximityWakeLock.release(flags), 这样就会取消P-Sensor监听器.
ok.. 那么接下来就是分析PowerManagerService里面这个P-Sensor是怎么工作的。


[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. SensorEventListener mProximityListener = new SensorEventListener() {  
  2.         public void onSensorChanged(SensorEvent event) {  
  3.             long milliseconds = SystemClock.elapsedRealtime();  
  4.             synchronized (mLocks) {  
  5.                 float distance = event.values[0];  //检测到手机和人体的距离  
  6.                 long timeSinceLastEvent = milliseconds - mLastProximityEventTime;  //这次检测和上次检测的时间差  
  7.                 mLastProximityEventTime = milliseconds;  //更新上一次检测的时间  
  8.                 mHandler.removeCallbacks(mProximityTask);   
  9.                 boolean proximityTaskQueued = false;  
  10.   
  11.   
  12.                 // compare against getMaximumRange to support sensors that only return 0 or 1  
  13.                 boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&  
  14.                         distance < mProximitySensor.getMaximumRange());  //如果距离小于某一个距离阈值,默认是5.0f,说明手机和脸部距离贴近,应该要熄灭屏幕。  
  15.   
  16.   
  17.                 if (mDebugProximitySensor) {  
  18.                     Slog.d(TAG, "mProximityListener.onSensorChanged active: " + active);  
  19.                 }  
  20.                 if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {  
  21.                     // enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing  
  22.                     mProximityPendingValue = (active ? 1 : 0);  
  23.                     mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);  
  24.                     proximityTaskQueued = true;  
  25.                 } else {  
  26.                     // process the value immediately  
  27.                     mProximityPendingValue = -1;  
  28.                     proximityChangedLocked(active);   //熄灭屏幕操作  
  29.                 }  
  30.   
  31.   
  32.                 // update mProximityPartialLock state  
  33.                 boolean held = mProximityPartialLock.isHeld();  
  34.                 if (!held && proximityTaskQueued) {  
  35.                     // hold wakelock until mProximityTask runs  
  36.                     mProximityPartialLock.acquire();  
  37.                 } else if (held && !proximityTaskQueued) {  
  38.                     mProximityPartialLock.release();  
  39.                 }  
  40.             }  
  41.         }  
  42.   
  43.   
  44.         public void onAccuracyChanged(Sensor sensor, int accuracy) {  
  45.             // ignore  
  46.         }  
  47.     };  

代码里面我已经有一些注释,下面来用文字描述下。
a.  首先会拿到这测距离变化的距离,float distance = event.values[0];
b.  检测这次距离变化和上次距离变化时间差,如果小于系统设置的阈值,则不会去熄灭屏幕。过于频繁的操作系统会忽略掉。所以,如果你感觉P-Sensor不够灵敏,就可以修改这个系统默认值

代码:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private static final int PROXIMITY_SENSOR_DELAY = 1000;  


如果你改的很小,就会发现P-Sensor会变得灵敏很多。。。
c.  嗯,如果P-Sensor检测到这次距离变化小于系统默认值,且这次是一次正常的变化,那么就应该去熄灭屏幕:
复制内容到剪贴板
代码:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. proximityChangedLocked(active);  


这里的active是true,同样,在这里它还会判断P-Sensor是否可以用,如果不可用,则返回。。忽略这次距离变化
复制内容到剪贴板
代码:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. if (!mProximitySensorEnabled) {  
  2.             Slog.d(TAG, "Ignoring proximity change after sensor is disabled");  
  3.             return;  
  4.         }  


如果一切都满足,则调用:
复制内容到剪贴板
代码:
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. goToSleepLocked(SystemClock.uptimeMillis(),  
  2.                         WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR);  


熄灭屏幕。。

[java] view plain copy
  1.   
0 0