首先说一下android平台下的11种感应器:
1. ACCELEROMETER 加速,描述加速度的。
2.GRAVITY 重力,这个在大家都知道。
3.GYROSCOPE 陀螺仪,对于物体跌落检测更强大些,开发游戏少了它会有点遗憾的,API
Level 9新增的类型。
4. LIGHT 光线感应器,很多Android手机的屏幕亮度是根据这个感应器的数组自动调节的。
5. LINEAR_ACCELERATION 线性加速器,API
Level 9新增的。
6. MAGNETIC_FIELD 磁极感应器。
7. ORIENTATION 方向感应器。
8. PRESSURE 压力感应器。
9. PROXIMITY 距离感应器,对于通话后关闭屏幕背光很有用。
10. ROTATION_VECTOR 旋转向量,Android
2.3新增的,如果我们过去处理图像会发现这个还是很有用的,不过这里还是对游戏开发起到辅助。
11. TEMPERATURE 温度感应器,可以获取手机的内部温度,不过和周边的有些差距,毕竟手机内部一般温度比较高。
要善于应用这些资源,今天要说的就是距离感应器。其这个锁频的原理也很简单,就是当有物体靠近距离感应器的时候,会触发事件,然后在事件里面申请设备电源锁,让屏幕处于黑屏出台,然后当物体离开距离感应器,释放设备电源锁,就ok了。下面看看代码
MainActivity.java 这个类很简单,就是启动一个Service。
public class MainActivity
extends Activity
{ /**
Called when the activity is first created. */ @Override public void onCreate(Bundle
savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); Intent
intent = new Intent(MainActivity. this ,
MyService. class ); startService(intent); } } |
然后就是MyService.java 主要内容
public class MyService
extends Service
{ private SensorManager
mManager; private Sensor
mSensor = null ; private SensorEventListener
mListener = null ; private PowerManager
localPowerManager = null ; private PowerManager.WakeLock
localWakeLock = null ; @Override public void onCreate()
{ //获取系统服务POWER_SERVICE,返回一个PowerManager对象 localPowerManager
= (PowerManager) getSystemService(Context.POWER_SERVICE); //获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是LogCat里用的Tag
localWakeLock
= this .localPowerManager.newWakeLock( 32 ,
"MyPower" ); //获取系统服务SENSOR_SERVICE,返回一个SensorManager对象 mManager
= (SensorManager) getSystemService(Context.SENSOR_SERVICE); //获取距离感应器对象 mSensor
= mManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); //注册感应器事件 mListener
= new SensorEventListener()
{ @Override public void onSensorChanged(SensorEvent
event) { float []
its = event.values; if (its
!= null &&
event.sensor.getType() == Sensor.TYPE_PROXIMITY) { System.out.println( "its[0]:" +
its[ 0 ]); //经过测试,当手贴近距离感应器的时候its[0]返回值为0.0,当手离开时返回1.0 if (its[ 0 ]
== 0.0 )
{ //
贴近手机 System.out.println( "手放上去了..." ); if (localWakeLock.isHeld())
{ return ; }
else localWakeLock.acquire(); //
申请设备电源锁 }
else { //
远离手机 System.out.println( "手拿开了..." ); if (localWakeLock.isHeld())
{ return ; }
else localWakeLock.setReferenceCounted( false ); localWakeLock.release();
//
释放设备电源锁 }
} } @Override public void onAccuracyChanged(Sensor
sensor, int accuracy)
{ } }; } @Override public int onStartCommand(Intent
intent, int flags,
int startId)
{ //注册监听 mManager.registerListener(mListener,
mSensor, SensorManager.SENSOR_DELAY_GAME); return super .onStartCommand(intent,
flags, startId); } @Override public void onDestroy()
{ //取消监听 mManager.unregisterListener(mListener); super .onDestroy(); } @Override public IBinder
onBind(Intent intent) { return null ; } } |
AndroidManifest.xml 中需要添加权限
<uses-permissionandroid:name="android.permission.DEVICE_POWER"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
由于时间原因,我这里只是实现了功能,还有很多要优化的地方,有需要的话自己可以加上。
优化1:当按下的时候,屏幕会锁住,但是感应器事件依然会触发,也就是说,当你挡住距离感应器,然后再放开,屏幕依然会亮。
解决方法:当系统锁屏或黑屏会广播两个消息分别是:ACTION_SCREEN_OFF和ACTION_SCREEN_ON,所以我们可以自己写个BroadcastReceiver来接受这个广播,并且做相应的处理。具体处理方法大家可以在黑屏的时候停止service,然后在屏幕亮后再启动service。或者更简单的定义个boolean变量,黑屏为false,亮的时候为true,然后判断在true的情况下才申请设备电源锁,应该都可以。大概代码如下
public class MyReceiver
extends BroadcastReceiver
{ @Override public void onReceive(Context
context, Intent intent) { String
action = intent.getAction(); if (action.equals( "android.intent.action.SCREEN_OFF" ))
{ }
else if (action.equals( "android.intent.action.SCREEN_ON" ))
{ } } } |
优化2:实现可以手动关闭和启动service。在MainActivity中可以添加个checkBox,以便开启和停止服务。这个应该很简单就不详细说明了。
优化3:开机自启动。这个就不说了,网上大把大把的资料。
最后再讲解下PowerManager这个类。
PowerManager这个类主要是用来控制电源状态的. 通过使用该类提供的api可以控制电池的待机时间,一般情况下不要使用。如果确实需要使用,那么尽可能的使用最低级别的WakeLocks锁。并且确保使用完后释放它。你可以通过context.getSystemService(Context.POWER_SERVICE)的方式获得PowerManager的实例。在PowerManager中,最主要的newWakeLock方法,SDK源码如下
/** *
Get a wake lock at the level of the flags parameter. Call *
{@link WakeLock#acquire() acquire()} on the object to acquire the *
wake lock, and {@link WakeLock#release release()} when you are done. * *
{@samplecode *PowerManager
pm = (PowerManager)mContext.getSystemService( *
Context.POWER_SERVICE); *PowerManager.WakeLock
wl = pm.newWakeLock( *
PowerManager.SCREEN_DIM_WAKE_LOCK *
| PowerManager.ON_AFTER_RELEASE, *
TAG); *wl.acquire(); *
// ... *wl.release(); *
} * *
@param flags Combination of flag values defining the requested behavior of the WakeLock. *
@param tag Your class name (or other tag) for debugging purposes. * *
@see WakeLock#acquire() *
@see WakeLock#release() */ public WakeLock
newWakeLock( int flags,
String tag) { return new WakeLock(flags,
tag); } |
这个方法将创建WakeLock对象,通过调用此对象的方法你就可以方便的去控制电源的状态。方法如下:
PowerManager
pm = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock
wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My
Tag" ); wl.acquire(); 屏幕将停留在设定的状态,一般为亮、暗状态 wl.release(); 释放掉正在运行的cpu或关闭屏幕。 |
flags参数说明:
* cpu screen keyboard
* PARTIAL_WAKE_LOCK on off off
* SCREEN_DIM_WAKE_LOCK on dim off
* SCREEN_BRIGHT_WAKE_LOCK on bright off
* FULL_WAKE_LOCK on bright bright
* PARTIAL_WAKE_LOCK on off off
* SCREEN_DIM_WAKE_LOCK on dim off
* SCREEN_BRIGHT_WAKE_LOCK on bright off
* FULL_WAKE_LOCK on bright bright
如果你持有PARTIAL_WAKE_LOCK锁,不论任何定时器甚至是按下电源按钮,cpu都将继续运行,无法进入休眠状态。除非你释放掉它。其他锁的话,虽然cpu也在运行,但是当用户按下电源按钮时,设备将立刻进入休眠状态。