基于距离传感器的自动锁屏程序

最近写了一个基于距离传感器锁屏的程序,在这里Mark一下。

手机为了节约能耗,一段时间没有操作就会自动锁屏,这带来了一个问题——你得不断的解锁,当然用了这么多年大家也许都习惯了。现在我想尝试一种既节约能耗,又不用频繁解锁的方法。


当手机被装到包里或者口袋里面,距离传感器都是可以检测出来的,所以为什么不根据这个特性来控制手机锁屏呢?

关于这个问题的详细讨论可以看看这里

1.程序功能


主界面


主要功能:

在后台创建一个后台服务,用来检测距离传感器是否被触发,如果触发就锁住屏幕。


带来的好处:

打开这个服务后,可以尝试把手机设置为不自动锁屏或者延长自动锁屏的时间,在不想用手机之后直接装到兜里面,由于距离传感器被触发,手机将自动锁屏。如果你的手机放在桌上,没有锁屏恰好有人想看你手机上的内容,你可以直接把手放到手机上,距离传感器被触发,就会锁住屏幕,这也比较符合人下意识的动作。对于像我这样不大喜欢频繁解锁的人,应该可以试试。


带来的问题:

一般的手机距离传感器应该是在听筒位置,在使用手机的时候一般不容易被触发。当然使用微信,或者语音助手的时候除外(我也在想解决这个问题的方案)。另外打电话接电话的时候必然会触发距离传感器。


解决方法:

尽量检测出在使用听筒时触发距离传感器的情况,然后在这种情况下,暂停锁屏服务,在不用听筒之后再将锁屏服务打开。在这个程序中,我只实现了检测来电和去电两种情形的检测,在打电话的时候,停止锁屏服务,在挂断电话后重启锁屏服务。

 

2.实现

2.1最关键的部分:锁屏功能

public static class Controller extends Activity {

	DevicePolicyManager mDPM;
	ComponentName mDeviceAdminSample;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

	// 首先我们要获得android设备管理代理
	mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);

	// LockScreen 继承自 DeviceAdminReceiver
	mDeviceAdminSample = new ComponentName(Controller.this,
		LockScreen.class);
	// 得到当前设备管理器有没有激活(获取权限)
	boolean active = mDPM.isAdminActive(mDeviceAdminSample);
	if (!active) {
		// 如果没有激活的话,就去提示用户激活(第一次运行程序时)
		getAdmin();
	} else {
		// 如果已经激活的话,就执行立即锁屏
		mDPM.lockNow();
	}
	// killMyself ,锁屏之后就立即kill掉我们的Activity,避免资源的浪费;
	//android.os.Process.killProcess(android.os.Process.myPid());
	finish();
	}

2.2后台服务

首先继承Android.app.Service类,然后实现 OnCreateOnStartOnDestroy方法,然后实现SensorEventListener接口中的两个函数——onAccuracyChangedonSensorChanged,一个是判断精度变化,一个是判断传感器距离变化。

最后将这个服务在Manifest文件中注册一个名称,然后在MainActivity中直接通过这个名称来启动和停止。

public class AutoLockService extends Service implements SensorEventListener {
}

2.3获取权限

首先在res目录下新建一个xml文件夹,然后在该文件夹下新建文件device_admin_sample.xml文件,其内容:

<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <force-lock />
    </uses-policies>

</device-admin>

然后在Manifest文件中注册一个广播接收者:


<!-- 接收请求Device Admin广播 -->        
<receiver
            android:name="org.hq.autolock.LockScreen"
            android:permission="android.permission.BIND_DEVICE_ADMIN" >
            <meta-data
                android:name="android.app.device_admin"
                android:resource="@xml/device_admin_sample" />
            <intent-filter>
                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
            </intent-filter>
        </receiver>

2.4判断来电和去电状态

继承BroadcastReceiver,已接收到广播就停止锁屏服务,判断挂机之后重新开启锁屏服务。

@Override
public void onReceive(Context context, Intent intent) {
	// TODO Auto-generated method stub
	//停止锁屏服务
	if( null == myintent ){
		myintent = new Intent("org.hq.autoLockService");
	}
	context.stopService(myintent);
	
	System.out.println("action"+intent.getAction());
	if(intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){
		//如果是去电(拨出)
		System.out.println("拨出");
	}else{
		//查了下android文档,貌似没有专门用于接收来电的action,所以,非去电即来电
		System.out.println("来电");
		TelephonyManager tm = (TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);   
		//如果挂断了,开启锁屏服务
		if( TelephonyManager.CALL_STATE_IDLE == tm.getCallState() ){
			if( null == myintent ){
				myintent = new Intent("org.hq.autoLockService");
			}
			context.startService(myintent);
		}
	}
}


2.5获取传感器信息

首先获取传感器管理类,通过SensorManager就可以获得手机上所有的传感器信息。要监测传感器参数变化,只需新建一个SensorEvenListener

sm = (SensorManager) getSystemService(SENSOR_SERVICE); // 获取传感器管理类
promixty = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY); // 获取距离传感器



3.题外话

在写完这个程序,装到手机里用了一段时间之后,发现用一个软件来实现锁屏其实没多大必要。很多智能手机用户已经适应甚至依赖那种解锁的感觉,所以并不感到繁琐。因此,用距离传感器来锁屏,也许大材小用没有必要。

最近看到一款应用,用距离传感器来自动接听来电,这个倒方便不少,省去了滑屏的动作。有兴趣的可以试试看~


工程源码:

http://download.csdn.net/detail/he_qiao_2010/5979623

没有积分的到这里下载:

http://pan.baidu.com/share/link?shareid=207532332&uk=1158831200

APK文件:

http://pan.baidu.com/share/link?uk=1158831200&shareid=2641184411

posted @ 2013-08-20 11:39  he_qiao_2010  阅读(229)  评论(0)    收藏  举报