文档管理中心
指南MDM能力开发指南

开发指南

概述

MDM能力SDK,包括两部分API,分别是设备管理类和应用权限管理类。这两部分API为在华为设备上使用的、经过授权的应用,提供了深度管理华为设备的功能。

(强制实现)权限使用声明、免责声明与软件许可协议

参见:权限使用要求。

架构

下图展示了MDM能力SDK的架构。

架构组成:

  • 应用:应用调用MDM能力SDK。

  • mdmkit-14.0.0.300.jar:MDM能力SDK的jar包。

  • 在华为设备上,开发者应用通过mdmkit-14.0.0.300.jar的接口调用,能直接完成功能设置,而在非华为设备上,开发者应用仅仅调用mdmkit-14.0.0.300.jar提供的接口,此时是空实现,不起作用。

MDM能力SDK使用指南

Android Studio开发指南

  1. 导入MDM Engine。

    方法一:通过HMS Toolkit插件实现自动导入。

    1. 安装HMS Toolkit插件,安装步骤请参见安装工具。
    2. 在菜单栏中选择“HMS > Repository”或者在工具栏中点击如下图标打开Repository。

    3. 勾选“MDM Engine”,然后点击“Apply”即可完成资源下载。
      说明

      导入后请修改模块级的build.gradle文件,使用compileOnly添加依赖,例如:compileOnly 'com.huawei.mdm:mdmkit:14.0.0.300'。

    方法二:手动修改gradle文件导入。
    1. 修改项目级的build.gradle文件,添加maven地址:url 'https://developer.huawei.com/repo'。

    2. 修改模块级的build.gradle文件,添加依赖:compileOnly 'com.huawei.mdm:mdmkit:10.1.0.300'。这里的10.1.0.300为MDM Engine的版本号,根据实际应用需要填写版本号。
      说明

      gradle脚本中依赖使用compileOnly类型。

    3. 进行Gradle同步,同步成功后就自动导入了MDM Engine。

  2. 开发应用。

    开发应用,编写代码,单元测试等。

    说明

    需要在AndroidManifest.xml文件中增加MDM API需要的权限和MDM的根权限"com.huawei.permission.sec.MDM"。

  3. 申请授权。

    目前有License和证书两种授权方式。申请流程及指导参见《接入准备》。

  4. 应用License/证书对APK授权。

    • 应用License对APK授权。

      通过调用HEM Kit的激活接口activeLicense()对APK授权。具体使用方法请参见DPC激活/去激活。

    • 应用证书对APK授权。

      方法一:通过HMS Toolkit插件将申请的证书打包到APK中。

      1. 安装HMS Toolkit插件,安装步骤请参见安装工具。
      2. 在菜单栏中选择“HMS > Coding Assistant”或者在工具栏中点击如下图标打开Coding Assistant。

      3. 在右侧的“Coding Assistant”中点击“MDM Engine”后即可看到证书打包工具。

      方法二:使用证书打包工具,将申请的证书打包到APK中。

      DevPack.exe是用于将华为证书打包到应用的工具。

      点击“OK”提示保存 “***_update.apk”,证书在APK的“META-INF”目录下。

      说明

      当前建议开发者使用Android V1+V2对APK进行签名,将证书集成到APK中后,还需要再次对此APK进行签名。

      点击下载:关于签名

MDM能力SDK使用详解

使用MDM能力API的前提是对开发者应用进行了授权(详见《接入准备》),授权后此应用就具有了调用MDM能力对应API的权限。

使用方法

由于开发者应用集成的mdmkit-14.0.0.300.jar,在非华为设备或者系统版本低于接口所支持的系统版本的华为设备上无具体实现,其接口会抛出NoExtAPIException,所以需要对此异常进行捕获,只有在华为设备支持的系统版本上运行后,才能调用具体实现。

  1. 激活开发者应用。

    收起
    自动换行
    深色代码主题
    复制
    1. import com.huawei.android.app.admin;
    2. //使用Android原生DevicePolicyManager
    3. mDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
    4. //创建当前APK的组件名称
    5. mAdminName = new ComponentName(this, SampleDeviceReceiver.class);
    6. ………
    7. //如果当前APK没有被设备管理激活,则先进行激活(Lisence授权可跳过此步骤)
    8. if (mDevicePolicyManager !=null && !mDevicePolicyManager.isAdminActive(mAdminName)) {
    9. Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
    10. intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdminName);
    11. mActivity.startActivityForResult(intent, REQUEST_ENABLE);
    12. }

  2. 使用相关管理类实现对应功能。

    例如:

    收起
    自动换行
    深色代码主题
    复制
    1. DeviceRestrictionManager restriction = new DeviceRestrictionManager();
    2. restriction.setWifiDisabled(adminName, true);
    详细内容请参见MDM能力示例工程。
    说明

    在调用设备管理类的接口之前,没有激活开发者应用,会抛出SecurityException异常。

MDM应用安全开发规范

本规范针对使用华为MDM能力的应用的组件安全、访问控制安全,描述可能导致安全漏洞或风险的常见编码错误。规范旨在减少组件访问权限控制不当等安全问题的发生。MDM应用开发应遵从规范要求。

MDM应用组件暴露可能带来的风险:可能会对外暴露内部接口,若被恶意应用利用,则会造成组件信息泄露或发起攻击。漏洞可能会对用户设备造成严重影响,并且由于MDM的设备管控能力,利用MDM应用的安全漏洞发起的攻击可能会影响设备的正常使用。

组件通用要求

对于Content Provider组件,若未设置exported属性:在Android 4.2版本之前(Android Sdk版本小于等于16),组件默认对外开放;在Android 4.2版本之后(Android Sdk版本大于16),组件默认不对外开放。

对于Activity、Service、Receiver组件,若未设置exported属性,且设置了intent-filter标签,则组件默认对外开放;若未设置exported属性,且未设置intent-filter标签,则组件默认不对外开放。

规则1 必须显式设置私有组件的exported属性为false

只在MDM应用程序内部使用的组件必须设置为非公开,以防受到其他应用程序的调用。非公开的组件必须显示的设置组件的exported属性为false,不要依赖属性默认值。

推荐做法是:

  • 显式设置私有组件的exported属性为false,且不要设置intent-filter标签;
  • 应用程序内部使用显式Intent访问私有组件。
错误示例:
收起
自动换行
深色代码主题
复制
  1. <activity
  2. android:name="com.huawei.PrivateActivity"
  3. android:label="@string/app_name" >
  4. <intent-filter>
  5. <action android:name="com.huawei.action.EVENT_CHANGE" />
  6. </intent-filter>
  7. </activity>
说明

PrivateActivity是一个私有组件,但是并未设置android:exported属性,并且声明了<intent-filter>标签,即任何指定com.huawei.action.EVENT_CHANGE行为的外部应用都可以访问该组件。

正确示例:
收起
自动换行
深色代码主题
复制
  1. <activity
  2. android:name="com.huawei.PrivateActivity"
  3. android:label="@string/app_name"
  4. android:exported="false" >
  5. </activity>
说明

私有组件显示设置exported属性为false,即只能通过显式Intent进行访问。

规则2 必须显式设置对外交互的组件的exported属性为true并设置访问权限

MDM应用程序的组件不只是在应用程序内部使用,很多情况下需要与外部进行交互。此时该组件应该在AndroidManifest.xml文件中显式设置android:exported属性为true,以表明该组件允许对外交互的,不要依赖属性默认值。

MDM程序内组件一旦允许公开,则会存在跨信任边界数据交互,若被恶意应用程序利用,可能会导致组件信息泄露或MDM能力被恶意使用;因此,MDM应用程序对外交互的组件必须在该组件标签(如<activity>)下,使用android:permission属性来设置访问权限。

例外情况:

对于纯系统行为注册的开放组件可不必设置访问权限。
收起
自动换行
深色代码主题
复制
  1. <activity
  2. android:name=".MainActivity"
  3. android:exported="true">
  4. <intent-filter>
  5. <action android:name="android.intent.action.MAIN" />
  6. <category android:name="android.intent.category.LAUNCHER" />
  7. </intent-filter>
  8. </activity>
错误示例:
收起
自动换行
深色代码主题
复制
  1. <activity
  2. android:name="com.huawei.PublicActivity"
  3. android:label="@string/app_name" >
  4. <intent-filter>
  5. <action android:name="com.huawei.action.EVENT_CHANGE" />
  6. </intent-filter>
  7. </activity>
说明

任何指定com.huawei.action.EVENT_CHANGE行为的外部应用都可以访问PublicActivity组件,恶意应用程序可能利用该组件获取敏感信息或发起拒绝服务攻击。

正确示例:
收起
自动换行
深色代码主题
复制
  1. <permission
  2. android:name="com.huawei.permission.ACCESS"
  3. android:protectionLevel="signature" >
  4. </permission>
  5. <application
  6. android:allowBackup="false"
  7. android:icon="@drawable/ic_launcher"
  8. android:label="@string/app_name"
  9. android:theme="@style/AppTheme" >
  10. <activity
  11. android:name="com.huawei.PublicActivity"
  12. android:label="@string/app_name"
  13. android:permission="com.huawei.permission.ACCESS"
  14. android:exported="true" >
  15. <intent-filter>
  16. <action android:name="com.huawei.action.EVENT_CHANGE" />
  17. </intent-filter>
  18. </activity>
  19. </application>
说明

在组件标签下设置android:exported属性为true,并设置android:permission属性,这样应用程序可以根据组件不同的安全策略,有针对性的设置访问权限,从而细粒度控制组件的访问权限,实现组件间权限隔离,更好的保护组件安全。

对于MDM应用,在<permission>标签中设置android:protectionLevel属性为signature,只允许拥有相同开发者签名的应用才能访问。

Broadcast组件要求

广播(Broadcast)为组件间通信提供了一种消息传递机制,这些组件可能是属于同一应用程序、也可能是属于不同应用程序。不同应用程序间的广播(Broadcast)使用进程间通信机制,广播权限设置不当,会给程序或系统带来安全上的风险。

规则1 必须对涉及发送敏感个人信息的Broadcast进行访问权限控制

对于涉及敏感个人信息的Broadcast,广播不能让其他应用接收到,应通过设置广播发送权限来限制谁有权接受广播消息。

错误示例:

收起
自动换行
深色代码主题
复制
  1. //Send Broadcast
  2. Intent intent = new Intent("com.huawei.action.EXAMPLE");
  3. intent.putExtra(KEY, SENSITIVE_DATA);
  4. sendBroadcast(intent);
说明

发送携带敏感个人(SENSITIVE_DATA)信息的广播也未指定Receiver权限,即任何声明拥有com.huawei.action.EXAMPLE行为的Receiver都能接收此广播。

正确示例:

在这种情况下,可以在应用发广播时添加参数声明Receiver所需的权限。

首先,在Broadcast应用的Androidmanifest.xml中定义权限:

收起
自动换行
深色代码主题
复制
  1. <permission
  2. android:name="com.huawei.permission.TEST"
  3. android:protectionLevel="signature" >
  4. </permission>

然后,在Send Broadcast时,将此权限参数传入:

收起
自动换行
深色代码主题
复制
  1. //Send Broadcast
  2. Intent intent = new Intent("com.huawei.action.EXAMPLE");
  3. intent.putExtra(KEY, SENSITIVE_DATA);
  4. sendBroadcast(intent,"com.huawei.permission.TEST");
说明

这里指定了Receiver权限,即只有声明了com.huawei.permission.TEST权限的Receiver才能接收此广播。发送广播时指定Receiver权限,能够很好的防范广播劫持攻击;在广播应用中声明权限,能够降低广播仿冒攻击的风险。通常广播发送方是诉求提出的主体,因此,该做法也是最为推荐的。

同时,在Receiver所在应用的AndroidManifest.xml中添加对应的权限:

收起
自动换行
深色代码主题
复制
  1. <uses-permission android:name="com.huawei.permission.TEST"/>

规则2 必须对接收Broadcast调用MDM能力进行访问权限控制

只接收特定来源的广播,通过设置接收器权限来限制广播来源,避免被恶意的同样ACTION的广播所干扰。造成MDM能力被其他恶意应用使用。

错误示例:

收起
自动换行
深色代码主题
复制
  1. //Receiver tag
  2. <receiver
  3. android:name=".ExampleReceiver"
  4. <intent-filter>
  5. <action android:name="com.huawei.action.EXAMPLE" />
  6. </intent-filter>
  7. </receiver>
  8. public class ExampleReceiver extends BroadcastReceiver {
  9. private DevicePolicyManager mDpm;
  10. @Override
  11. public void onReceive(Context context, Intent intent) {
  12. // invoke mdm
  13. mDpm.setCameraDisabled(admin, true);
  14. }
  15. }
说明

Broadcast的<receiver>标签中未声明android:permission属性来限制广播来源。恶意应用可以通过com.huawei.action.EXAMPLE使用MDM能力,影响设备的正常使用。

正确示例:

在这种情况下,需要在Receiver应用的<receiver>标签中声明android:permission属性以及广播发送方所在应用具有的权限。

首先,在Receiver应用的AndroidManifest.xml中定义权限:

收起
自动换行
深色代码主题
复制
  1. <permission
  2. android:name="com.huawei.permission.TEST"
  3. android:protectionLevel="signature" >
  4. </permission>

然后,在注册Receiver时添加相应权限:

  • 方式一 在静态<receiver>标签中添加相应权限的声明
收起
自动换行
深色代码主题
复制
  1. <receiver
  2. android:name=".ExampleReceiver"
  3. android:permission="com.huawei.permission.TEST"
  4. android:exported="true" >
  5. <intent-filter>
  6. <action android:name="com.huawei.action.EXAMPLE" />
  7. </intent-filter>
  8. </receiver>
  • 方式二 在动态注册receiver时添加相应权限的声明
收起
自动换行
深色代码主题
复制
  1. registerReceiver(receiver, filter, "com.huawei.permission.TEST", null);
说明

设置权限后,该Receiver只能接收来自具有com.huawei.permission.TEST权限的应用发出的广播。

同时,在广播发送方所在应用的AndroidManifest.xml中声明使用该权限:

收起
自动换行
深色代码主题
复制
  1. <uses-permission android:name="com.huawei.permission.TEST"/>
在 指南 中进行搜索
请输入您想要搜索的关键词