本节通过 SDK 中的一个实例来讲解设备管理 API 的使用方法,运行效果如图 1 所示。
图 1 设备管理应用程序
该范例程序提供了一个使用设备管理 API 进行设备管理的模板,它展示了设备管理 API 的用户交互方法。其功能如下:
系统管理员可以使用设备管理 API 来编写一个应用,强制执行远程/本地设备安全政策。这部分给出了创建一个设备管理应用的实现步骤。
对于使用设备管理 API 的应用程序,其 AndroidManifest.xml 代码必须包含如下信息。
设备管理范例程序的 AndroidManifest.xml 代码如下:
<activity android:name=".app.DeviceAdminSample"
android:label="@string/activity_sample_device_admin">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".app.DeviceAdminSample$DeviceAdminSampleReceiver"
android:label="@string/sample_device_admin"
android:description="@string/sample_device_admin_description"
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>
注意:
1)在项目的 ApiDemos/res/values/strings.xml 中设置以下属性值。
关于更多资源的相关信息,请参看 Application Resources。
2)android:permission="android.permission.BIND_DEVICE_ADMIN"是 DeviceAdminReceiver 子类具备的权限,保证系统的应用权限(其他应用都不会拥有该权限),对滥用设备管理的其他应用提供防御。
3)android:name="android.app.action.DEVICE_ADMIN_ENABLED"是 DeviceAdminReceiver 的子类的 Action 类型,用于对设备进行管理。当用户开启设备管理应用时,它被设置为接收者。代码通常在 onEnabled() 中处理。为了得到支持,接收者也必须得到 BIND_DEVICE_ADMIN 权限以便其他应用程序无法拒绝。
4)当用户开启设备管理应用时,给接收者权限去执行,回应给系统特定的接收事件的广播。当出现匹配的事件时,应用就可以强加一个规范。比如,如果用户尝试设置一个新的但不符合规范的密码,应用可以提示用户选择一个不同的符合规范的密码。
5)android:resource="@xml/device_admin_sample" 声明使用在元数据中的安全规范。元数据为指定设备管理员提供了更多被 DeviceAdminInfo 类所解析的信息。
以下是 device_admin_sample.xml 的代码。
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-polocies>
<limit-password/>
<watch-login/>
<reset-password/>
<force-lock/>
<wipe-data/>
<expire-password/>
<encrypted-storage/>
<disable-camers/>
</uses-polocies>
</device-admin>
在设备管理应用设计中,不需要包括所有的策略,只要有和应用相关的策略就可以。
设备管理 API 包含以下几个类。
1)DeviceAdminReceiver
该类是完成设备管理组件的基类。这个类提供了一个解释系统发送的原始 Intent 动作的方便途径。设备管理程序必须包含一个它的子类。
2)DevicePolicyManager
该类负责管理在设备上执行的安全策略。大多数客户端要发布一个已经被当前用户启用的 DeviceAdminReceiver。DevicePolicyManager 为至少一个 DeviceAdminReceiver 实例管理安全策略。
3)DeviceAdminInfo
该类是用来为系统管理组件指定元数据的。
这些类提供一个设备管理应用实现的基础。接下来将描述如何使用 DeviceAdminReceiver 和 DevicePolicyManager API 来编写一个设备管理应用。
要创建一个设备管理应用程序,必须实现一个 DeviceAdminReceiver 的子类。
DeviceAdminReceiver 包含一系列回调函数,这些回调函数会在具体的事件发生时被调用。
以下代码只在 DeviceAdminReceiver 子类中简单地显示了 Toast,作为对相应事件的应答。
要创建一个设备管理应用程序,必须实现一个 DeviceAdminReceiver 的子类。
DeviceAdminReceiver 包含一系列回调函数,这些回调函数会在具体的事件发生时被调用。
以下代码只在 DeviceAdminReceiver 子类中简单地显示了 Toast,作为对相应事件的应答。
public class DeviceAdminSample extends DeviceAdminReceiver {
void showToast(Context context, String msg) {
String status = context.getString(R.string.admin_receiver_status, msg);
Toast.makeText(context, status, Toast.LENGTH_SHORT) .show ();
}
@Override
public void onEnabled(Context context, Intent intent) {
showToast(context, context.getString(R.string.admin_receiver_status_enabled));
}
@Override
public CharSequence onDisableRequested(Context context, Intent intent) {
return context.getString(R.string.admin_receiver_status_disable_warning);
}
@Override
public void onDisabled(Context context, Intent intent) {
showToast (context, context.getString (R.string.admin receiver status disabled));
}
@Override
public void onPasswordChanged(Context context, Intent intent) {
showToast(context,context.getString(R.string.admin_receiver_status_pw_changed));
}
...
}
用户启用程序是设备管理程序要处理的最重要的事件之一。用户必须明确启用设备管理程序才能使安全策略在设备上得以执行。如果用户选择不启用,那么安全策略就不会被执行,用户也就无法使用设备管理程序。
只要用户发出了 ACTION_ADD_DEVICE_ADMIN 的 Intent 动作,应用程序即可被启用。在以下示例中,用户点击“Enable Admin” 选择框,设备就会提示用户已经启用了设备管理程序,如图 2 所示。
图 2 启用程序
下面是当用户点击“Enable Admin”选择框时要执行的代码,结果触发了 onPreferenceChange() 回调函数。当用户改变 Preference 的值时,就会调用这个回调函数。如果用户启用程序,界面就会提示用户正在启用程序,如图 2 所示,否则就是禁止程序。
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (super.onPreferenceChange(preference,newValue)){
return true;
}
boolean value = (Boolean) newValue;
if (preference == mEnableCheckbox) {
if (value != mAdminActive) {
if (value) {
// Launch the activity to have the user enable our admin.
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,mDeviceAdminSample);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
mActivity.getString(R.string.add_admin_extra_app_text));
startActivityForResult(intent, REQUEST_CODE_ENABLE_ADMIN);
// return false - don't update checkbox until we're really active
return false;
} else {
mDPM.removeActiveAdmin(mDeviceAdminSample);
enableDeviceCapabilitiesArea(false);
mAdminActive = false;
}
}
} else if (preference == mDisableCameraCheckbox) {
mDPM.setCameraDisabled(mDeviceAdminSample, value);
...
}
return true;
}
其中,intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDeviceAdminSample) 说明 mDeviceAdminSample 是目标策略(DeviceAdminReceiver 是一个组件)。这些代码会调用图 2 的界面,让用户选择是否添加系统管理员。
使用 DevicePolicyManager 的 isAdminActive() 方法可以实现确定管理程序是否已经被启用。需要注意的是,该方法需要一个 DeviceAdminReceiver 类型的参数。
DevicePolicyManager mDPM;
...
private boolean isActiveAdmin() {
return mDPM.isAdminActive(mDeviceAdminSample);
}
DevicePolicyManager 是设备管理的主类。通过它可以实现屏幕锁定、屏幕亮度调节、出厂设置等功能。DevicePolicyManager 为一个或多个 DeviceAdminReceiver 类的实例管理策略。
获得 DevicePolicyManager 实例的方法可以通过以下代码实现:
本小节主要描述如何使用 DevicePolicyManager 执行设置密码策略、设备解锁策略和指定数据擦除功能等。
DevicePolicyManager 包括许多用来设置和执行设备密码策略的API。在设备管理 API 中,密码只是用来解锁屏幕的。本小节描述了密码相关的任务。
以下代码用于显示一个用户界面提醒用户设置密码:
解锁策略可以由 DevicePolicyManager 的常量来设置。
例如,按需求设置数字密码,其设置策略如下:
DevicePolicyManager mDPM;
ComponentName mDeviceAdminSample;
...
mDPM.setPasswordQuality(mDeviceAdminSample,DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC);
从 Android 3.0 开始,DevicePolicyManager 就提供了一些能很好地调节密码内容的方法。例如,可以要求密码必须有 n 个大写字母。下面这些就是提供功能的方法:
设置最少两个大写字母的密码,其代码如下:
DevicePolicyManager mDPM;
ComponentName mDeviceAdminSample;
int pwMinUppercase = 2;
...
mDPM.setPasswordMinimumUpperCase(mDeviceAdminSample,pwMinUppercase);
可以指定密码的最小长度,例如:
可以设置允许密码输入错误的最大次数,超过这个次数设备就要擦除数据(恢复出厂设置),例如:
从 Android 3.0 开始,可以使用 setPasswordExpirationTimeout() 方法设置密码何时失效,系统会以毫秒为单位倒计时,例如:
从 Android 3.0 开始,可以使用 setPasswordHistoryLength() 限制用户使用的密码要多久不能重复,这个方法中包含 length 参数,该参数用来设置要记录密码的个数。当该策略被激活时,用户就不能使用所设定范围内的旧密码当作新密码使用,防止用户一直使用同一个密码。这个策略通常与 setPasswordExpirationTimeout() 一起使用,迫使用户每过一段时间就得换一个新的密码。
例如,下面的代码可以防止用户使用近期用过的 5 个密码:
在设定的时间内没有使用设备,就把设备锁屏,例如:
还可以使设备立即锁屏:
可以使用 DevicePolicyManager 的 wipeData() 方法使设备恢复出厂设置。在设备被偷或者丢失的情况下非常有用。当然,恢复出厂设置要慎用。例如,在用户输入错误密码达到固定次数之后,可以使用 setMaximumFailedPasswordsForWipe() 来擦除设备数据,代码如下:
wipeData() 方法的参数是一个整数,这里暂时必须为 0。
Android N 系统可以禁用摄像头,但不是永久禁用。摄像头可以动态地禁用/启用在不同的上下文、时间等。
使用 setCameraDisabled() 来设置摄像头是否被禁用。例如,下面的代码就根据选择框的状态来决定摄像头是否被禁用:
从 Android 3.0 开始,可以使用 setStorageEncryption() 方法来设置加密存储,前提是设备必须支持,例如: