【Android设备管理】 利用DevicePolicyManager执行屏幕锁定

来源:互联网 发布:2004年3d开奖数据 编辑:程序博客网 时间:2024/06/04 18:48

 [原文]http://blog.csdn.net/feng88724/article/details/6323544

Android手机一般不用时,都会通过电源键来锁定屏幕同时关闭屏幕灯。

其实从API Level 8 (也就是Android 2.2) 开始, Android提供了DevicePolicyManager类, 可以让你的应用程序也能执行屏幕锁定等操作。

 

锁定效果:

  

 

 

下面我们来看一下具体如何操作。 要让自己的应用实现该屏幕锁定,主要需要用到以下几个类:

 

 

DevicePolicyManager

这是设备管理的主类。通过它可以实现屏幕锁定、屏幕亮度调节、出厂设置等功能。

 

 

DeviceAdminReceiver

 

 该类继承自 BroadcastReceiver 。 从源码可以看到,其实就是实现了一个OnReceive方法,该方法中根据不同的Action,执行相应的操作。 比如,如果激活成功,那么Action就是ACTION_DEVICE_ADMIN_ENABLED, 据此调用 onEnabled 方法。

 

系统源码:

[java] view plaincopyprint?
  1. /** 
  2.  * Intercept standard device administrator broadcasts.  Implementations 
  3.  * should not override this method; it is better to implement the 
  4.  * convenience callbacks for each action. 
  5.  */  
  6. @Override  
  7. public void onReceive(Context context, Intent intent) {  
  8.     String action = intent.getAction();  
  9.     if (ACTION_PASSWORD_CHANGED.equals(action)) {  
  10.         onPasswordChanged(context, intent);  
  11.     } else if (ACTION_PASSWORD_FAILED.equals(action)) {  
  12.         onPasswordFailed(context, intent);  
  13.     } else if (ACTION_PASSWORD_SUCCEEDED.equals(action)) {  
  14.         onPasswordSucceeded(context, intent);  
  15.     } else if (ACTION_DEVICE_ADMIN_ENABLED.equals(action)) {  
  16.         onEnabled(context, intent);  
  17.     } else if (ACTION_DEVICE_ADMIN_DISABLE_REQUESTED.equals(action)) {  
  18.         CharSequence res = onDisableRequested(context, intent);  
  19.         if (res != null) {  
  20.             Bundle extras = getResultExtras(true);  
  21.             extras.putCharSequence(EXTRA_DISABLE_WARNING, res);  
  22.         }  
  23.     } else if (ACTION_DEVICE_ADMIN_DISABLED.equals(action)) {  
  24.         onDisabled(context, intent);  
  25.     }  
  26. }  
 

 

DeviceAdminInfo

定义设备管理类的 meta 信息。 什么意思呢? 就是定义可用的权限。define policy that this device admin can use。

 

 

比如 DeviceAdminReceiver.USES_POLICY_FORCE_LOCK , 这个就是本次要用的"强制锁定屏幕"的权限. 不过这些权限一般都直接通过XML文件来定义。 稍后你就会看到。

 

 

 


 

下面我们就来看下如何实现屏幕锁定。

注意,此处讲的屏幕锁定, 其实还是调用的系统的锁定方式。

在 "设置" - “位置与安全” - "更改屏幕锁定" 中可以设置锁定方式,一共有四种:

1. 无锁

2. 图案锁 (就是九宫图)

3. PIN锁

4. 密码锁

 

你的手机设置了哪个锁, 调用这个API时就会显示哪个锁 !

 

(锁定类型设置画面)

 

 

 

第一步: 写一个布局文件,该布局上有四个按钮, 分别对应 "激活设备管理权限" 、 "禁用设备管理权限"、"系统锁"、"自定义锁"。 

其中"自定义锁"在下一篇博文中讲。本次暂时不用。

 

布局文件如下:

[xhtml] view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout  
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:gravity="center"  
  5.     android:id="@+id/rlTextDescBlock"  
  6.     android:layout_width="wrap_content"  
  7.     android:layout_height="wrap_content">  
  8.     <LinearLayout  
  9.         android:id="@+id/layout1"  
  10.         android:orientation="horizontal"  
  11.         android:layout_width="fill_parent"  
  12.         android:layout_height="wrap_content"  
  13.         android:layout_marginTop="30px">  
  14.         <Button   
  15.             android:id="@+id/active"  
  16.             android:textSize="14.0sp"  
  17.             android:textStyle="bold"  
  18.             android:textColor="#ff5779a7"  
  19.             android:background="@drawable/detail_redirect_button_bg"  
  20.             android:layout_width="fill_parent"  
  21.             android:layout_height="wrap_content"  
  22.             android:layout_marginLeft="10.0dip"  
  23.             android:text="激活"   
  24.             android:layout_weight="1.0" />  
  25.         <Button   
  26.             android:id="@+id/unactive"  
  27.             android:textSize="14.0sp"  
  28.             android:textStyle="bold"  
  29.             android:textColor="#ff5779a7"  
  30.             android:background="@drawable/detail_comment_button_bg"  
  31.             android:paddingRight="10.0dip"  
  32.             android:layout_width="fill_parent"  
  33.             android:layout_height="wrap_content"  
  34.             android:layout_marginRight="10.0dip"  
  35.             android:text="禁用"  
  36.             android:layout_weight="1.0" />  
  37.     </LinearLayout>  
  38.       
  39.     <LinearLayout  
  40.         android:layout_below="@id/layout1"  
  41.         android:orientation="horizontal"  
  42.         android:layout_width="fill_parent"  
  43.         android:layout_height="wrap_content"  
  44.         android:layout_marginTop="30px">  
  45.         <Button   
  46.             android:id="@+id/syslock"  
  47.             android:textSize="14.0sp"  
  48.             android:textStyle="bold"  
  49.             android:textColor="#ff5779a7"  
  50.             android:background="@drawable/detail_redirect_button_bg"  
  51.             android:layout_width="fill_parent"  
  52.             android:layout_height="wrap_content"  
  53.             android:layout_marginLeft="10.0dip"  
  54.             android:text="系统锁屏"   
  55.             android:layout_weight="1.0" />  
  56.         <Button  
  57.             android:id="@+id/custlock"  
  58.             android:textSize="14.0sp"  
  59.             android:textStyle="bold"  
  60.             android:textColor="#ff5779a7"  
  61.             android:background="@drawable/detail_comment_button_bg"  
  62.             android:paddingRight="10.0dip"  
  63.             android:layout_width="fill_parent"  
  64.             android:layout_height="wrap_content"  
  65.             android:layout_marginRight="10.0dip"  
  66.             android:text="自定义锁屏"   
  67.             android:layout_weight="1.0" />  
  68.     </LinearLayout>  
  69. </RelativeLayout>  
 

 

效果图:

 

 

 

下面就对应的一个个实现功能。

 

1. "激活" 功能。

 

STEP1:初始化设备管理需要的几个类:

[java] view plaincopyprint?
  1. //获取设备管理服务  
  2. policyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);  
  3.   
  4. //AdminReceiver 继承自 DeviceAdminReceiver  
  5. componentName = new ComponentName(this, AdminReceiver.class);  

 

其中: AdminReceiver 类的代码如下:

[java] view plaincopyprint?
  1. package com.yfz.broadcast;  
  2. import com.yfz.log.Logger;  
  3. import android.app.admin.DeviceAdminInfo;  
  4. import android.app.admin.DeviceAdminReceiver;  
  5. import android.app.admin.DevicePolicyManager;  
  6. import android.content.ComponentName;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9. import android.content.pm.ResolveInfo;  
  10. import android.os.IBinder;  
  11. import android.widget.Toast;  
  12. public class AdminReceiver extends DeviceAdminReceiver {  
  13.     @Override  
  14.     public DevicePolicyManager getManager(Context context) {  
  15.         Logger.d("------" + "getManager" + "------");  
  16.         return super.getManager(context);  
  17.     }  
  18.     @Override  
  19.     public ComponentName getWho(Context context) {  
  20.         Logger.d("------" + "getWho" + "------");  
  21.         return super.getWho(context);  
  22.     }  
  23.       
  24.     /** 
  25.      * 禁用 
  26.      */  
  27.     @Override  
  28.     public void onDisabled(Context context, Intent intent) {  
  29.         Logger.d("------" + "onDisabled" + "------");  
  30.           
  31.         Toast.makeText(context, "禁用设备管理", Toast.LENGTH_SHORT).show();  
  32.           
  33.         super.onDisabled(context, intent);  
  34.     }  
  35.     @Override  
  36.     public CharSequence onDisableRequested(Context context, Intent intent) {  
  37.         Logger.d("------" + "onDisableRequested" + "------");  
  38.         return super.onDisableRequested(context, intent);  
  39.     }  
  40.       
  41.     /** 
  42.      * 激活 
  43.      */  
  44.     @Override  
  45.     public void onEnabled(Context context, Intent intent) {  
  46.         Logger.d("------" + "onEnabled" + "------");  
  47.           
  48.         Toast.makeText(context, "启动设备管理", Toast.LENGTH_SHORT).show();  
  49.           
  50.         super.onEnabled(context, intent);  
  51.     }  
  52.     @Override  
  53.     public void onPasswordChanged(Context context, Intent intent) {  
  54.         Logger.d("------" + "onPasswordChanged" + "------");  
  55.         super.onPasswordChanged(context, intent);  
  56.     }  
  57.     @Override  
  58.     public void onPasswordFailed(Context context, Intent intent) {  
  59.         Logger.d("------" + "onPasswordFailed" + "------");  
  60.         super.onPasswordFailed(context, intent);  
  61.     }  
  62.     @Override  
  63.     public void onPasswordSucceeded(Context context, Intent intent) {  
  64.         Logger.d("------" + "onPasswordSucceeded" + "------");  
  65.         super.onPasswordSucceeded(context, intent);  
  66.     }  
  67.     @Override  
  68.     public void onReceive(Context context, Intent intent) {  
  69.         Logger.d("------" + "onReceive" + "------");  
  70.           
  71.         super.onReceive(context, intent);  
  72.     }  
  73.     @Override  
  74.     public IBinder peekService(Context myContext, Intent service) {  
  75.         Logger.d("------" + "peekService" + "------");  
  76.         return super.peekService(myContext, service);  
  77.     }  
  78.       
  79. }  
 

 

继承了DeviceAdminReceiver,没有做什么特别操作,仅仅在激动、禁用时输出一个提示消息。

同时,像普通Broadcast类一样,该类也需要在  AndroidManifest.xml 文件中注册。

如下:

[xhtml] view plaincopyprint?
  1. <!-- 设备管理 -->  
  2. <receiver android:name=".broadcast.AdminReceiver"  
  3.     android:label="@string/device"  
  4.     android:description="@string/device_des"  
  5.     android:permission="android.permission.BIND_DEVICE_ADMIN">  
  6.     <meta-data android:name="android.app.device_admin"  
  7.         android:resource="@xml/lock_screen" />  
  8.     <intent-filter>  
  9.         <action  
  10.             android:name="android.app.action.DEVICE_ADMIN_ENABLED" />  
  11.     </intent-filter>  
  12. </receiver>  
 

 

其中 

android:permission="android.permission.BIND_DEVICE_ADMIN" 和

 

<intent-filter>

<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />

</intent-filter>

 

是必须的。

 

android:resource="@xml/lock_screen" 对应的就是权限说明文件。

本次仅需要强制锁定权限。 如下:

[xhtml] view plaincopyprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <device-admin  
  3.   xmlns:android="http://schemas.android.com/apk/res/android">  
  4.     <uses-policies>  
  5.         <!-- 强行锁定 -->  
  6.         <force-lock />  
  7.     </uses-policies>  
  8. </device-admin>  
 

 

 

STEP2: "激活"按钮 执行代码:

 

[java] view plaincopyprint?
  1. /** 
  2.  * 激活设备管理权限 
  3.  * 成功执行激活时,DeviceAdminReceiver中的 onEnabled 会响应 
  4.  */  
  5. private void activeManage() {  
  6.     // 启动设备管理(隐式Intent) - 在AndroidManifest.xml中设定相应过滤器  
  7.     Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);  
  8.       
  9.     //权限列表  
  10.        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);  
  11.          
  12.        //描述(additional explanation)  
  13.        intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "------ 其他描述 ------");  
  14.          
  15.        startActivityForResult(intent, 0);  
  16. }  
 

 

这边就是用了一个隐式Intent ,通过这个Intent (DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)跳转到 权限提醒页面。 同时传递了两个参数EXTRA_DEVICE_ADMIN 、 EXTRA_ADD_EXPLANATION。

EXTRA_DEVICE_ADMIN参数中说明了用到哪些权限, EXTRA_ADD_EXPLANATION参数为附加的说明。

 

就这样,一个激活功能就完成了。 激活页面如下:

 

 

上图中" 设备管理软件说明: 我们不是黑客,请放心!" 对应的是 AndroidManifest.xml文件中  android:description="@string/device_des"。

 

"------ 其他描述 ------" 就是之前传的 EXTRA_ADD_EXPLANATION 参数。

 

个人觉得两者要一个就可以了, 不知道为什么要提供两个。

 

STEP 3: 点击"激活"。 

此时该应用就拥有了设备管理权限。 激活时 AdminReceiver 类的  onEnabled方法会被调用。

 

2. “禁用” 功能。

 

   如果在上面选择了"激活", 那么你这个应用就可以一直使用这些权限了,不需要再次激活。 但是如果想"禁用",该怎么做呢?

答案很简单,只要调用下面的方法即可.

[java] view plaincopyprint?
  1. /** 
  2.  * 禁用设备管理权限 
  3.  * 成功执行禁用时,DeviceAdminReceiver中的 onDisabled 会响应 
  4.  */  
  5. private void unActiveManage() {  
  6.     Logger.d("------ unActiveManage ------");  
  7.     boolean active = policyManager.isAdminActive(componentName);  
  8.        if (active) {  
  9.         policyManager.removeActiveAdmin(componentName);  
  10.        }  
  11. }  
 

 

禁用时 AdminReceiver 类的  onDisabled方法会被调用。

 

3. “系统锁”

    其实到这已经非常简单了,所有的配置及初始化,都在激活时做了。

    下面直接上调用系统锁的代码:

[java] view plaincopyprint?
  1. boolean active = policyManager.isAdminActive(componentName);  
  2. if (active) {  
  3.     policyManager.lockNow();  
  4. }  

 

到此为止, 屏幕锁定结束了。

 

附上主要类的代码:

[java] view plaincopyprint?
  1. package com.yfz;  
  2. import com.yfz.broadcast.AdminReceiver;  
  3. import com.yfz.log.Logger;  
  4. import android.app.Activity;  
  5. import android.app.ActivityManager;  
  6. import android.app.AlertDialog;  
  7. import android.app.admin.DevicePolicyManager;  
  8. import android.content.ComponentName;  
  9. import android.content.Context;  
  10. import android.content.Intent;  
  11. import android.os.Bundle;  
  12. import android.view.View;  
  13. import android.view.View.OnClickListener;  
  14. import android.widget.Button;  
  15. public class Lesson13 extends Activity implements OnClickListener {  
  16.       
  17.     private DevicePolicyManager policyManager;  
  18.     private ComponentName componentName;  
  19.       
  20.     @Override  
  21.     protected void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         setContentView(R.layout.lesson13);  
  24.           
  25.         //获取设备管理服务  
  26.         policyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);  
  27.           
  28.         //AdminReceiver 继承自 DeviceAdminReceiver  
  29.         componentName = new ComponentName(this, AdminReceiver.class);  
  30.           
  31.         init();  
  32.     }  
  33.     private void init() {  
  34.         Button active = (Button)findViewById(R.id.active);  
  35.         Button unactive = (Button)findViewById(R.id.unactive);  
  36.         Button syslock = (Button)findViewById(R.id.syslock);  
  37.           
  38.         active.setOnClickListener(this);  
  39.         unactive.setOnClickListener(this);  
  40.         syslock.setOnClickListener(this);  
  41.     }  
  42.     @Override  
  43.     public void onClick(View v) {  
  44.         switch(v.getId()) {  
  45.             case R.id.active:  
  46.                 activeManage();  
  47.                 break;  
  48.             case R.id.unactive:  
  49.                 unActiveManage();  
  50.                 break;  
  51.             case R.id.syslock:  
  52.                 systemLock();  
  53.                 break;  
  54.             default:  
  55.                 break;  
  56.         }  
  57.     }  
  58.       
  59.     /** 
  60.      * 激活设备管理权限 
  61.      * 成功执行激活时,DeviceAdminReceiver中的 onEnabled 会响应 
  62.      */  
  63.     private void activeManage() {  
  64.         // 启动设备管理(隐式Intent) - 在AndroidManifest.xml中设定相应过滤器  
  65.         Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);  
  66.           
  67.         //权限列表  
  68.         intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);  
  69.           
  70.         //描述(additional explanation)  
  71.         intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "------ 其他描述 ------");  
  72.           
  73.         startActivityForResult(intent, 0);  
  74.     }  
  75.       
  76.     /** 
  77.      * 禁用设备管理权限 
  78.      * 成功执行禁用时,DeviceAdminReceiver中的 onDisabled 会响应 
  79.      */  
  80.     private void unActiveManage() {  
  81.         Logger.d("------ unActiveManage ------");  
  82.         boolean active = policyManager.isAdminActive(componentName);  
  83.         if (active) {  
  84.             policyManager.removeActiveAdmin(componentName);  
  85.         }  
  86.     }  
  87.       
  88.     /** 
  89.      * 调出系统锁 
  90.      */  
  91.     private void  systemLock() {  
  92.         Logger.d("------ Lock Screen ------");  
  93.         boolean active = policyManager.isAdminActive(componentName);  
  94.         if (active) {  
  95.             policyManager.lockNow();  
  96.         }  
  97.     }  
  98. }  
 

 


 

最后说一下,设备管理拥有的权限,一共就5个。

看配置文件中的说明吧。

 

[xhtml] view plaincopyprint?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <device-admin  
  3.   xmlns:android="http://schemas.android.com/apk/res/android">  
  4.     <uses-policies>  
  5.         <!-- 强行锁定 -->  
  6.         <force-lock />  
  7.         <!-- 清除所有数据(恢复出厂设置) -->  
  8.         <wipe-data />  
  9.          <!-- 重置密码 -->  
  10.         <reset-password />  
  11.         <!-- 限制密码选择 -->  
  12.          <limit-password />  
  13.          <!-- 监控登录尝试 -->  
  14.           <watch-login />  
  15.     </uses-policies>  
  16. </device-admin>  
 

 

所有权限都申请时的效果图:

 

 

 

强制屏幕锁定功能, 可以应用于一些安全软件, 比如手机安全卫士, 当手机丢失后,用户发送指令短信、或者邮件到该手机上, 让手机强制锁屏。 这样的话,及时别人捡到了,也无法使用。 

 

不过一般手机用户可能不一定会设定手机锁,因此调用系统锁可能并没有多大作用,因此下一篇我们做一个自定义锁, 该锁只在需要时启用。

0 0