课程内容

  1. 定义和声明您的策略
  2. 创建 Device Administration Receiver
  3. 激活设备管理器
  4. 实现设备策略控制器

您还应该阅读

动手试试

下载示例代码DeviceManagement.zip

从 Android 2.2 (API level 8)版本开始,Android平台通过设备管理API提供了系统级的设备管理能力。

这节课程将会介绍如何创建一个安全相关的程序,该程序通过执行设备管理策略来保护设备信息的安全。具体来说,该程序可以配置锁屏密码的强度,通过该配置来保护敏感的信息。这个和大家在公司使用的Windows电脑一样, 公司会定义好电脑密码的策略 — 比如要求是大于8位同时包含3种不同类型字符的密码 — 这样来保证电脑不会轻易的被破解掉密码,从而保护电脑里面的资料。

定义和声明您的策略

首先,需要定义支持的策略种类。设备策略包含锁屏密码强度、密码失效时间 等。

您必须在 res/xml/device_admin.xml 文件中定义使用的策略集合,程序会应用该策略到设备上。同时在Manifest文件中需要引用声明的策略集合。

每个声明的策略都对应DevicePolicyManager类中的一个或者几个相关的函数。如果一个程序尝试调用一个没有在XML文件中声明过的策略函数,会抛出一个 SecurityException 异常。如果程序想管理其他类型的策略,可以使用其他的权限 — 比如 force-lock。在后面您会看到,在设备管理器的激活流程中会有一个系统界面告诉用户您所声明的策略集合列表。

下面的代码在res/xml/device_admin.xml文件中定义了limit password 策略:

<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <limit-password />
    </uses-policies>
</device-admin>

在 manifest 文件中引用定义的策略:

<receiver android:name=".Policy$PolicyAdmin" android:permission="android.permission.BIND_DEVICE_ADMIN">
    <strong><meta-data android:name="android.app.device_admin"
        android:resource="@xml/device_admin" /></strong>
    <intent-filter>
        <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
    </intent-filter>
</receiver>

创建 Device Administration Receiver

当您定义的策略事件发生的时候会通知您创建的这个设备管理器Receiver。可以根据情况覆盖(Override)需要的回调函数。

在Device Admin这个示例程序中,如果用户撤销了设备管理器,示例程序所配置的策略信息将会清除。您需要考虑实现符合您的使用情况的业务逻辑。例如,程序可以删除一些敏感信息来减轻安全风险、还可以禁用远程同步功能 等。

不要忘了在manifest文件中注册您的Receiver。

public static class PolicyAdmin extends DeviceAdminReceiver {

    @Override
    public void onDisabled(Context context, Intent intent) {
        // Called when the app is about to be deactivated as a device administrator.
        // Deletes previously stored password policy.
        super.onDisabled(context, intent);
        SharedPreferences prefs = context.getSharedPreferences(APP_PREF, Activity.MODE_PRIVATE);
        prefs.edit().clear().commit();
    }
}

激活设备管理器

在执行任何策略之前,用户需要手工的激活设备管理器。下面的代码演示了如何触发设置界面来让用户激活您的设备管理器程序。包含一个介绍文本内容告诉用户为啥您的程序需要激活为设备管理器是个不错的选择, 通过在Intent中设置 EXTRA_ADD_EXPLANATION 字段。

device-mgmt-activate-device-admin
device-mgmt-activate-device-admin

Figure 1. 在用户激活界面提供关于您的设备策略的描述信息。

if (!mPolicy.isAdminActive()) {

    Intent activateDeviceAdminIntent =
        new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);

    activateDeviceAdminIntent.putExtra(
        DevicePolicyManager.EXTRA_DEVICE_ADMIN,
        mPolicy.getPolicyAdmin());

    // It is good practice to include the optional explanation text to
    // explain to user why the application is requesting to be a device
    // administrator. The system will display this message on the activation
    // screen.
    activateDeviceAdminIntent.putExtra(
        DevicePolicyManager.EXTRA_ADD_EXPLANATION,
        getResources().getString(R.string.device_admin_activation_message));

    startActivityForResult(activateDeviceAdminIntent,
        REQ_ACTIVATE_DEVICE_ADMIN);
}

如果用户选择 “Activate 激活” 您的程序为设备管理器,然后就可以开始配置和应用您的策略了。

另外您的程序还要处理其他情况,比如用户点击了取消(Cancel)按钮、或者按了返回键、或者用户按了Home键。因此需要在设置策略Activity的 onResume() 函数中处理这种情况。如果需要的话再次把激活设备管理员的界面显示给用户。

实现设备策略控制器

一旦成功了激活为设备管理器后,程序就可以应用定义的策略了。需要注意的是,随着Android的发展,在新的版本中可能会添加新的策略。所以在应用策略之前判断下当前设备的版本是否支持该策略是比较保险的做法。例如, Password Minimum Upper Case policy(密码最少包含几个大写字符的策略)是在 API level 11 (Honeycomb) 版本引入的。下面的代码展示了如何在运行时检测版本信息:

DevicePolicyManager mDPM = (DevicePolicyManager)
        context.getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName mPolicyAdmin = new ComponentName(context, PolicyAdmin.class);
...
mDPM.setPasswordQuality(mPolicyAdmin, PASSWORD_QUALITY_VALUES[mPasswordQuality]);
mDPM.setPasswordMinimumLength(mPolicyAdmin, mPasswordLength);
if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.HONEYCOMB) {
    mDPM.setPasswordMinimumUpperCase(mPolicyAdmin, mPasswordMinUpperCase);
}

现在程序可以执行策略了。但是目前程序还没有访问当前使用的锁屏密码,不知道用户当前的设置是否符合您定义的策略要求。通过Device Policy Manager API可以判断当前用户设置的密码是否符合您定义的策略。如果发现当前的密码不符合安全策略,设备管理API不会自动的去处理这种情况。您的程序需要自己启动设置程度中的修改密码界面,例如:

if (!mDPM.isActivePasswordSufficient()) {
    ...
    // Triggers password change screen in Settings.
    Intent intent =
        new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
    startActivity(intent);
}

通常情况下,用户可以自由的选择任何一种锁屏机制,例如 None(无)、 Pattern(图案)、PIN (numeric)、或者 Password密码 (alphanumeric)。 当选择了一种密码策略,上面的包含强度比较弱的锁屏机制就会被禁用。例如,如果配置了“Numeric”类型的密码强度,用户只能使用 PIN (numeric) 和 Password (alphanumeric) 这两种锁屏机制。

当设置的密码通过了配置的策略,程序就允许访问敏感的内容了。

if (!mDPM.isAdminActive(..)) {
    // Activates device administrator.
    ...
} else if (!mDPM.isActivePasswordSufficient()) {
    // Launches password set-up screen in Settings.
    ...
} else {
    // Grants access to secure content.
    ...
    startActivity(new Intent(context, SecureActivity.class));
}

原文:http://blog.chengyunfeng.com/?p=325