使用适用于 Android 的 Microsoft Intune App SDK,可以将Intune应用保护策略 (也称为 MAM 策略) 合并到本机 Java/Kotlin Android 应用中。 Intune托管的应用程序与 Intune 应用 SDK 集成。 当Intune主动管理应用时,Intune管理员可以轻松地将应用保护策略部署到Intune托管的应用。
注意
本指南分为几个不同的阶段。 首先查看 规划集成。
阶段 7:应用参与功能
阶段目标
- 了解 Intune 应用 SDK 提供的应用参与功能。
- 集成与应用和用户相关的应用参与功能。
- 测试这些功能的集成。
什么是“应用参与功能”?
此 SDK 集成过程尝试将开发人员需要编写的特定于应用的代码量降至最低。 通过成功完成 SDK 集成的前一阶段,你的应用现在强制实施大多数应用保护策略设置,例如文件加密、复制/粘贴限制、屏幕截图阻止和数据传输限制。
但是,某些设置需要应用特定的代码才能正确强制执行;这些设置称为应用参与功能。 通常,SDK 没有足够的有关应用程序代码或最终用户方案的上下文来自动强制实施这些设置,因此依赖于开发人员适当地调用 SDK API。
应用参与功能不一定是可选的。 根据应用的现有功能,可能需要这些功能。 有关详细信息 ,请参阅 SDK 集成的关键决策 。
本指南的上一阶段已经介绍了多个应用参与功能:
- 阶段 5:多标识中所述的多标识。
- 阶段 6:应用程序配置 中所述的应用配置。
本指南的其余部分介绍了剩余的应用参与功能集:
- 强制实施限制将文件保存到本地存储或从云存储打开文件的策略。
- 强制实施限制通知中内容的策略。
- 强制实施保护备份数据的策略。
- 如果应用具有自定义屏幕捕获代码) ,则强制实施限制屏幕捕获 (策略。
- 支持应用保护 CA。
- 注册 SDK 中的通知。
- 应用自定义应用程序主题。
- 使用来自Intune的受信任证书,确保本地终结点的信任链。
应用参与功能基础知识
AppPolicy 接口包含许多方法,可通知应用是否允许某些作。
大多数应用参与功能包括:
- 在应用代码中标识正确位置以检查是否允许某个作。
- 调用 方法
AppPolicy以检查是否允许作,具体取决于当前配置的策略。 - 根据结果,允许作完成,或者在作被阻止时修改应用行为。
若要检索 AppPolicy 实例,请使用 MAMPolicyManager 方法之一,例如 getPolicy(final Context context) 或 getPolicyForIdentityOID(final String oid)。
AppPolicy 中的信息方法
中 AppPolicy 并非每个方法都与应用参与功能相关联。
某些方法是信息性的,并且会提供当前配置了哪些策略的应用数据,即使 SDK 会自动强制执行这些策略也是如此。
这些方法的存在使你的应用有机会在配置特定策略时提供自定义用户体验。
示例:确定是否阻止屏幕截图
如果应用具有允许用户获取屏幕截图的控件,请考虑在应用保护策略阻止屏幕截图时禁用或隐藏该控件。
应用可以通过调用 MAMPolicyManager.getPolicy(currentActivity).getIsScreenCaptureAllowed()来检查。
用于限制应用与设备或云存储位置之间的数据传输的策略
许多应用允许最终用户将数据保存到本地文件存储或云存储服务或从本地文件存储服务打开数据。 Intune App SDK 允许 IT 管理员通过限制应用将数据保存到和打开数据的位置来防止数据流入和数据泄露。
注意
如果你的应用允许直接从应用保存到个人或云位置,或者允许将数据直接打开到应用中,则必须实现此Intune应用 SDK 应用参与功能**,使 IT 管理员能够阻止此保存和打开。
保存到设备或云存储
API getIsSaveToLocationAllowedForOID 允许应用根据配置的策略,知道是否允许对给定标识保存到特定位置:
MAMPolicyManager.getPolicy(currentActivity).getIsSaveToLocationAllowedForOID(
SaveLocation service, String oid);
若要确定应用是否应实现getIsSaveToLocationAllowedForOID检查,请通过查看下表来确定应用是否支持数据出口:
service 参数: SaveLocation 枚举值 |
用例 | 关联的 OID |
|---|---|---|
ONEDRIVE |
应用正在将数据保存到 OneDrive。 | 用于云服务身份验证和Microsoft Entra身份验证的帐户的 OID。 如果此帐户不存在或 OID 未知,请使用 null。 |
SHAREPOINT |
应用程序正在将数据保存到 SharePoint。 | 用于云服务身份验证和Microsoft Entra身份验证的帐户的 OID。 如果此帐户不存在或 OID 未知,请使用 null。 |
BOX |
应用正在将数据保存到 Box。 | 用于云服务身份验证和Microsoft Entra身份验证的帐户的 OID。 如果此帐户不存在或 OID 未知,请使用 null。 |
LOCAL |
应用将数据保存到设备上的外部存储位置,该位置 不是 应用的专用存储。 | 此存储位置不被视为云服务,应始终与 OID 参数一 null 起使用。 |
PHOTO_LIBRARY |
应用正在将数据保存到 Android 本地照片存储。 | 本地照片存储不被视为云服务,应始终与 OID 参数一 null 起使用。 |
IMANAGE |
应用正在将数据保存到 iManage。 | 用于云服务身份验证和Microsoft Entra身份验证的帐户的 OID。 如果此帐户不存在或 OID 未知,请使用 null。 |
EGNYTE |
应用正在将数据保存到 Egnyte。 | 用于云服务身份验证和Microsoft Entra身份验证的帐户的 OID。 如果此帐户不存在或 OID 未知,请使用 null。 |
ACCOUNT_DOCUMENT |
应用将数据保存到与应用中的帐户关联的位置,并且不是此表中的特定云位置之一。 使用此位置可以确定是否可以在多标识应用中的帐户之间传递数据。 |
用于Microsoft Entra身份验证的帐户的 OID。 如果此帐户不存在或 OID 未知,请使用 null。 |
OTHER |
应用将数据保存到此表中未指定且不符合 的条件 ACCOUNT_DOCUMENT的位置。 |
oid不会为此位置评估 ,应为 null。 |
始终允许放置在专用应用存储中的文件,这些文件要么是应用作所必需的,要么是临时下载以供显示的文件;无需检查 getIsSaveToLocationAllowedForOID。
执行检查 SaveLocation.LOCAL
- 保存在专用应用存储外部的文件。
- 下载到专用应用存储(无需执行应用作)的文件 (例如,当用户显式选择下载到设备) 时。
注意
检查保存策略时, oid 应是与要保存到的云服务关联的帐户的 OID, (此帐户不一定与拥有) 保存文档的帐户相同。
从本地或云存储位置打开数据
API getIsOpenFromLocationAllowedForOID 可让应用根据配置的策略,知道是否允许从特定位置打开给定标识:
MAMPolicyManager.getPolicy(currentActivity).getIsOpenFromLocationAllowedForOID(
OpenLocation location, String oid);
若要确定应用是否应实现getIsOpenFromLocationAllowedForOID检查,请查看下表,确定应用是否支持数据入口:
location 参数: OpenLocation 枚举值 |
用例 | 关联的 OID |
|---|---|---|
ONEDRIVE_FOR_BUSINESS |
应用正在从 OneDrive 打开数据。 | 用于云服务身份验证和Microsoft Entra身份验证的帐户的 OID。 如果此帐户不存在或 OID 未知,请使用 null。 |
SHAREPOINT |
应用程序正在从 SharePoint 打开数据。 | 用于云服务身份验证和Microsoft Entra身份验证的帐户的 OID。 如果此帐户不存在或 OID 未知,请使用 null。 |
CAMERA |
应用正在打开来自设备相机的数据。 | 一个 null 值,因为设备相机不是云服务。 |
LOCAL |
应用从设备上的外部存储位置( 不是 应用的专用存储)打开数据。 | 尽管外部存储不是云服务,但需要参数 oid ,因为它指示所有权。• 对于标识标记的文件: oid 应是文件所有者的标识。• 对于没有标识标记的文件: oid 应为 null。 |
PHOTO_LIBRARY |
应用正在打开 Android 本地照片存储中的数据。 | 本地照片存储不被视为云服务,应始终与 OID 参数一 null 起使用。 |
ACCOUNT_DOCUMENT |
该应用正在从与应用中的帐户关联的位置打开数据,并且不是此表中的特定云位置之一。 使用此位置可以确定是否可以在多标识应用中的帐户之间传递数据。 |
用于Microsoft Entra身份验证的帐户的 OID。 如果此帐户不存在或 OID 未知,请使用 null。 |
OTHER |
应用正在从此表中未指定且不符合 的条件 ACCOUNT_DOCUMENT的位置打开数据。 |
oid不会为此位置评估 ,应为 null。 |
注意
检查打开策略时,oid应是与从 (打开的文件或云服务关联的帐户的 OID,不一定与) 打开文档的帐户相同。
提示
为方便起见,SDK 提供了 方法, AppPolicy.isOpenFromLocalStorageAllowed 该方法为本地存储中的文件采用 File 参数。
对于策略强制实施,此方法在功能上与调用AppPolicy.getIsOpenFromLocationAllowedForOID(OpenLocation.LOCAL, oid)相同,只不过它处理从 File分析文件所有者的 oid 。
共享阻止的对话框
SDK 提供了一个对话框,用于在 MAM 策略阻止数据传输作时通知用户。
每当 getIsSaveToLocationAllowedForOID 或 getIsOpenFromLocationAllowedForOID API 调用导致保存/打开作被阻止时,都应向用户显示对话框。
对话框显示一条泛型消息,并在关闭时返回到调用 Activity 。
若要显示对话框,请添加以下代码:
MAMUIHelper.showSharingBlockedDialog(currentActivity)
允许文件共享
如果不允许保存到公共存储位置,则应用仍应允许用户查看文件,方法是将其下载到 应用专用存储 ,然后使用系统选择器打开这些文件。
限制通知内内容的策略
对于单标识应用,Intune应用 SDK 的默认行为会尝试在应用保护策略限制通知时阻止所有通知。
SDK 的默认行为是有限的。 SDK 不能自动遵循“阻止组织数据”值,该值仅用于从通知中删除托管内容。 对于多标识应用,SDK 无法确定哪些通知包含托管内容。
如果你的应用显示通知,并且它是多标识和/或需要遵循“阻止组织数据”值,则它必须在显示通知之前检查与通知关联的帐户的通知限制策略。
若要确定是否强制实施策略,请进行以下调用:
NotificationRestriction notificationRestriction =
MAMPolicyManager.getPolicyForIdentityOID(notificationIdentityOid).getNotificationRestriction();
返回的 NotificationRestriction 枚举具有以下值:
NotificationRestriction 枚举 |
预期应用行为 |
|---|---|
BLOCKED |
应用 不得 显示与此策略关联的帐户的任何通知。 对于单一标识应用,Intune应用 SDK 会自动阻止所有通知,无需额外的代码。 |
BLOCK_ORG_DATA |
应用必须显示不包含组织数据的修改通知。 |
UNRESTRICTED |
应用应显示所有通知。 |
如果应用未正确调用 getNotificationRestriction,MAM SDK 会尽最大努力自动限制 仅针对单标识应用的通知。
在这种情况下, BLOCK_ORG_DATA 被视为 相同 BLOCKED ,并且根本不显示通知。
若要进行更精细的控制,检查 的值getNotificationRestriction并相应地修改应用通知。
用于保护备份数据的策略
Intune App SDK 可以阻止数据上传到 Android 的内置备份和还原功能。 有关 Android 中的备份和还原的详细信息,请参阅 Android API 指南 ,以及更改 备份和还原中的 Android S /12 中引入的更改。
应用的自动备份
从 Android M 开始,无论应用的目标 API 如何,Android 都会 为应用提供 Google Drive 的自动完整备份 。
Intune允许你使用 Android 提供的所有自动备份功能,包括在 XML 中定义自定义规则的功能,以及特定的Intune集成指南,以确保数据保护适用。
在应用的清单中配置备份行为
默认情况下, android:allowBackup 设置为 true ,如 启用和禁用备份中所述。
如果应用不需要完整的备份和还原功能,请将 设置为 android:allowBackupfalse。
在这种情况下,无需执行进一步作,公司数据将保留在应用中。
如果应用需要完整的备份和还原功能,请将 设置为 android:allowBackuptrue 并执行以下步骤:
如果你的应用不使用自己的自定义
BackupAgent,请使用默认的 MAMBackupAgent 启用符合策略Intune自动完整备份。 在应用清单中放置以下内容:<application ... android:fullBackupOnly="true" android:backupAgent="com.microsoft.intune.mam.client.app.backup.MAMDefaultBackupAgent" ...> </application>可选。 如果实现自定义
BackupAgent,则必须使用 MAMBackupAgent 或 MAMBackupAgentHelper。 请参阅以下部分。 请考虑切换到Intune的 MAMDefaultBackupAgent,如步骤 1 中所述,它可在 Android M 及更高版本上轻松备份。确定应用应接收 (未筛选、筛选或未) 的完整备份类型时,请将 属性
android:fullBackupContent设置为true、false或应用中的 XML 资源。然后,必须将 的值
android:fullBackupContent复制到元数据标记中com.microsoft.intune.mam.FullBackupContent,对于支持在 API 31 中添加的 XML 配置格式的应用,则复制到com.microsoft.intune.mam.DataExtractionRules元数据标记中。示例 1:如果希望应用具有不带排除项的完整备份,则必须将属性和元数据标记设置为 true:
<application ... android:fullBackupContent="true" ...> </application> ... <meta-data android:name="com.microsoft.intune.mam.FullBackupContent" android:value="true" /> <meta-data android:name="com.microsoft.intune.mam.DataExtractionRules" android:value="true" />示例 2:如果希望应用使用其自定义
BackupAgent并选择退出完全、Intune策略合规的自动备份,则必须将属性和元数据标记设置为 false:<application ... android:fullBackupContent="false" ...> </application> ... <meta-data android:name="com.microsoft.intune.mam.FullBackupContent" android:value="false" /> <meta-data android:name="com.microsoft.intune.mam.DataExtractionRules" android:value="false" />示例 3:如果希望应用根据 XML 文件中定义的自定义规则进行完整备份,请将属性和元数据标记设置为同一 XML 资源:
<application ... android:fullBackupContent="@xml/my_full_backup_content_scheme" android:dataExtractionRules="@xml/my_data_extraction_rules_scheme" ...> </application> ... <meta-data android:name="com.microsoft.intune.mam.FullBackupContent" android:resource="@xml/my_full_backup_content_scheme" /> <meta-data android:name="com.microsoft.intune.mam.DataExtractionRules" android:resource="@xml/my_data_extraction_rules_scheme" />
键/值备份
“键/值备份”选项可用于所有 API 8+,并将应用数据上传到 Android 备份服务。 每个应用的数据量限制为 5 MB。 如果使用键/值备份,则必须使用 BackupAgentHelper 或 BackupAgent。
BackupAgentHelper
在本机 Android 功能和Intune MAM 集成方面,BackupAgentHelper 比 BackupAgent 更易于实现。
BackupAgentHelper 允许开发人员将整个文件和共享首选项分别注册到 FileBackupHelper 和 SharedPreferencesBackupHelper (,) 创建后将这些文件和共享首选项添加到 BackupAgentHelper。
按照以下步骤将 BackupAgentHelper 与 Intune MAM 配合使用:
若要将多标识备份与
BackupAgentHelper配合使用,请按照 扩展 BackupAgentHelper 的 Android 指南进行作。让类扩展 BackupAgentHelper、FileBackupHelper 和 SharedPreferencesBackupHelper 的 MAM。
| Android 类 | MAM 等效项 |
|---|---|
BackupAgentHelper |
MAMBackupAgentHelper |
FileBackupHelper |
MAMFileBackupHelper |
SharedPreferencesBackupHelper |
MAMSharedPreferencesBackupHelper |
遵循这些准则可以成功执行多标识备份和还原。
BackupAgent
借助 BackupAgent,可以更明确地了解备份的数据。 由于开发人员负责实现,因此需要采取更多步骤来确保Intune提供适当的数据保护。 由于大部分工作都是由你作为开发人员完成的,因此Intune集成会稍微增加一些。
集成 MAM:
仔细阅读 密钥/值备份 的 Android 指南,特别是 扩展 BackupAgent ,以确保 BackupAgent 实现遵循 Android 指南。
让类扩展 MAMBackupAgent。
多标识备份:
在开始备份之前,检查 IT 管理员允许在多标识方案中备份计划备份的文件或数据缓冲区。 在
isBackupAllowedMAMFileProtectionManager 和 MAMDataProtectionManager 中使用 来确定此行为。 如果不允许备份文件或数据缓冲区,则不应将其包含在备份中。在备份过程中的某个时刻,如果要备份在步骤 1 中签入的文件的标识,则必须使用计划从中提取数据的文件进行调用
backupMAMFileIdentity(BackupDataOutput data, File … files)。 此方法会自动创建新的备份实体,并将它们写入到 中BackupDataOutput。 还原时会自动使用这些实体。
多标识还原: 数据备份指南指定用于还原应用程序数据的常规算法,并在 扩展 BackupAgent 部分提供代码示例。 若要成功执行多标识还原,必须遵循此代码示例中提供的常规结构,并特别注意以下几点:
必须使用
while(data.readNextHeader())* 循环来遍历备份实体。如果
data.getKey()与在 中onBackup编写的密钥不匹配,则必须调用data.skipEntityData()。 如果没有此步骤,还原可能不会成功。在 * 构造中使用
while(data.readNextHeader())备份实体时避免返回 ,因为在这种情况下,我们自动写入的任何实体都将丢失。
- 其中
data是应用在还原时收到的 MAMBackupDataInput 的本地变量名称。
自定义屏幕捕获限制
如果你的应用包含绕过 Android 级别FLAG_SECURE限制的Window自定义屏幕捕获功能,则必须检查屏幕捕获策略,然后才允许完全访问该功能。
例如,如果应用使用自定义呈现引擎将当前视图呈现为 PNG 文件,则必须首先检查 AppPolicy.getIsScreenCaptureAllowed()。
注意
如果应用不包含任何自定义或非Microsoft屏幕捕获功能,则无需执行任何作即可限制屏幕捕获。
屏幕捕获策略在所有 MAM 集成应用的级别自动强制实施 Window 。
将根据需要阻止 OS 或其他应用在应用中捕获 Window 的任何尝试。
例如,如果用户尝试通过 Android 的内置屏幕截图或屏幕录制功能捕获应用的屏幕,则自动限制捕获,而无需应用参与。
支持应用保护 CA
应用保护 CA (条件访问) (也称为基于应用的 CA)限制对资源的访问。 Intune应用保护策略必须先管理应用程序,然后才能访问这些资源。 Microsoft Entra ID强制实施此策略,方法是要求应用在授予令牌以访问受条件访问保护的资源之前,先Intune应用保护策略进行注册并由应用保护策略进行管理。
注意
应用保护 CA 支持需要Microsoft身份验证库 (MSAL) 版本 1.0.0 或更高版本。
使用 MSAL 处理不符合要求
当应用获取帐户的令牌时,MSAL 库可能会返回或引发 , MsalIntuneAppProtectionPolicyRequiredException 以指示不符合应用保护策略管理。
可以从异常中提取更多参数以用于修正合规性 (请参阅 MAMComplianceManager) 。
修正成功后,应用可以通过 MSAL 再次尝试获取令牌。
MAMComplianceManager
从 MSAL 收到需要策略的错误时,将使用 MAMComplianceManager 接口。
它包含 [remediateCompliance] 方法,应调用该方法以尝试将应用置于合规状态。
可以获取对 的引用, MAMComplianceManager 如下所示:
MAMComplianceManager mgr = MAMComponents.get(MAMComplianceManager.class);
// make use of mgr
返回 MAMComplianceManager 的实例保证不为 null。
package com.microsoft.intune.mam.policy;
public interface MAMComplianceManager {
void remediateCompliance(String upn, String aadId, String tenantId, String authority, boolean showUX);
}
方法remediateCompliance()尝试将应用置于管理之下,以满足Microsoft Entra ID授予所请求令牌的条件。
可以从 MSAL AuthenticationCallback.onError() 方法接收的异常中提取前四个参数。
最后一个参数是一个布尔值,用于控制在合规性尝试期间是否显示用户体验。
remediateCompliance 显示简单的阻止进度对话框,因此应用无需在此作期间显示自定义体验。
仅当合规性修正正在进行时,才会显示此对话框。 它不显示最终结果。
你的应用可以为通知注册接收方 COMPLIANCE_STATUS ,以处理合规性修正尝试的成功或失败。
有关更多详细信息 ,请参阅合规性状态通知 。
remediateCompliance() 可能会启动 MAM 注册,作为建立合规性的一部分。
如果应用已注册注册通知接收方,则可能会收到注册通知。
应用的已注册 MAMServiceAuthenticationCallback 调用了其 acquireToken() 方法来获取注册的令牌。
acquireToken() 在应用获取自己的令牌之前调用 。 应用在成功获取令牌后执行的任何簿记或帐户创建任务可能尚未完成。
在这种情况下,回调必须能够获取令牌。
如果无法从 acquireToken()返回令牌,则合规性修正尝试将失败。
如果稍后使用所请求资源的有效令牌调用 updateToken ,则合规性修正会立即使用给定令牌恢复。
注意
仍可以在 中 acquireToken() 获取无提示令牌,因为已指导用户在异常发生之前 MsalIntuneAppProtectionPolicyRequiredException 安装代理并注册设备。
此过程会导致中转站在其缓存中具有有效的刷新令牌,从而允许代理以无提示方式获取请求的令牌。
下面是一个示例,该示例在 方法中 AuthenticationCallback.onError() 接收需要策略的错误,并调用 MAMComplianceManager 来处理该错误。
public void onError(@Nullable MsalException exc) {
if (exc instanceof MsalIntuneAppProtectionPolicyRequiredException) {
final MsalIntuneAppProtectionPolicyRequiredException policyRequiredException =
(MsalIntuneAppProtectionPolicyRequiredException) ex;
final String upn = policyRequiredException.getAccountUpn();
final String aadId = policyRequiredException.getAccountUserId();
final String tenantId = policyRequiredException.getTenantId();
final String authority = policyRequiredException.getAuthorityURL();
MAMComplianceManager complianceManager = MAMComponents.get(MAMComplianceManager.class);
complianceManager.remediateCompliance(upn, aadId, tenantId, authority, showUX);
}
}
符合性状态通知
如果应用注册类型的 COMPLIANCE_STATUS通知,系统会发送 , MAMComplianceNotification 以通知应用合规性修正尝试的最终状态。
有关 注册的详细信息,请参阅从 SDK 注册通知 。
public interface MAMComplianceNotification extends MAMUserNotification {
MAMCAComplianceStatus getComplianceStatus();
String getComplianceErrorTitle();
String getComplianceErrorMessage();
}
方法 getComplianceStatus() 将符合性修正尝试的结果作为 [MAMCAComplianceStatus] 枚举的值返回。
| 状态代码 | 解释 |
|---|---|
UNKNOWN |
状态未知。 此状态可能指示意外的失败原因。 有关详细信息,请参阅公司门户日志。 |
COMPLIANT |
合规性修正成功,应用现在符合策略。 应重试 MSAL 令牌获取。 |
NOT_COMPLIANT |
修正符合性尝试失败。 应用不符合要求,在更正错误条件之前,不应重试 MSAL 令牌获取。 包括 MAMComplianceNotification 额外的错误信息。 |
SERVICE_FAILURE |
尝试从Intune服务检索合规性数据时失败。 有关详细信息,请参阅公司门户日志。 |
NETWORK_FAILURE |
连接到 Intune 服务时出错。 恢复网络连接后,应用应重试其令牌获取。 |
CLIENT_ERROR |
由于客户端相关的问题(例如缺少或不正确的用户令牌),修正合规性的尝试失败。 包括 MAMComplianceNotification 更多错误信息。 |
PENDING |
修正符合性尝试失败,因为服务不会在时间限制到期之前发送状态响应。 应用应稍后再次尝试获取其令牌。 |
COMPANY_PORTAL_REQUIRED |
必须在设备上安装公司门户才能成功进行合规性修正。 如果已安装,则必须重启应用。 对话框提示用户重启应用。 |
如果符合性状态为 MAMCAComplianceStatus.COMPLIANT,则应用应为其自己的资源) 重新初始化其原始令牌获取 (。
如果符合性修正尝试失败, getComplianceErrorTitle() 和 getComplianceErrorMessage() 方法将返回本地化字符串,应用可以选择向最终用户显示这些字符串。
应用无法解决大多数错误情况。 通常,帐户创建或登录失败,并允许用户稍后重试。
如果故障持续存在,公司门户日志可能有助于确定原因。 最终用户可以提交日志。 有关详细信息,请参阅 上传和电子邮件日志。
下面是使用匿名类注册接收器以实现 MAMNotificationReceiver 接口的示例:
final MAMNotificationReceiverRegistry notificationRegistry = MAMComponents.get(MAMNotificationReceiverRegistry.class);
// create a receiver
final MAMNotificationReceiver receiver = new MAMNotificationReceiver() {
public boolean onReceive(MAMNotification notification) {
if (notification.getType() == MAMNotificationType.COMPLIANCE_STATUS) {
MAMComplianceNotification complianceNotification = (MAMComplianceNotification) notification;
// take appropriate action based on complianceNotification.getComplianceStatus()
// unregister this receiver if no longer needed
notificationRegistry.unregisterReceiver(this, MAMNotificationType.COMPLIANCE_STATUS);
}
return true;
}
};
// register the receiver
notificationRegistry.registerReceiver(receiver, MAMNotificationType.COMPLIANCE_STATUS);
注意
必须在调用 remediateCompliance() 之前注册通知接收器,以避免可能导致缺少通知的争用条件。
声明对应用保护 CA 的支持
应用准备好处理应用 CA 修正后,可以告知Microsoft标识应用已准备好应用 CA。 若要在 MSAL 应用程序中执行此作,请使用“protapp”的客户端功能生成公共客户端
{
"client_id" : "[YOUR_CLIENT_ID]",
"authorization_user_agent" : "DEFAULT",
"redirect_uri" : "[YOUR_REDIRECT_URI]",
"multiple_clouds_supported":true,
"broker_redirect_uri_registered": true,
"account_mode": "MULTIPLE",
"client_capabilities": "protapp",
"authorities" : [
{
"type": "AAD",
"audience": {
"type": "AzureADandPersonalMicrosoftAccount"
}
}
]
}
完成这些步骤后,继续 执行验证应用保护 CA。
实现说明
注意
应用的 MAMServiceAuthenticationCallback.acquireToken() 方法应将标志acquireTokenSilentAsync()的 forceRefreshfalse 传递给 。
AcquireTokenSilentParameters acquireTokenSilentParameters =
builder.withScopes(Arrays.asList(scopes))
.forceRefresh(false)
.build();
acquireTokenSilentAsync(acquireTokenSilentParameters);
注意
如果要在修正尝试期间显示自定义阻止 UX,则应将 showUX 参数的 false 传递给 remediateCompliance()。
在调用 remediateCompliance()之前,必须确保先显示 UX 并注册通知侦听器。
这可以防止出现在快速失败时 remediateCompliance() 可能会错过通知的争用情况。
例如, onCreate() Activity 子类的 或 onMAMCreate() 方法是注册通知侦听器,然后调用 remediateCompliance()的理想位置。
remediateCompliance()的参数可以作为意向附加项传递给 UX。
收到符合性状态通知后,可以显示结果或完成活动。
注意
remediateCompliance() 注册帐户并尝试注册。 获取主令牌后,无需调用 registerAccountForMAM() ,但这样做不会造成伤害。
另一方面,如果应用无法获取其令牌并想要删除用户帐户,则必须调用 unregisterAccountForMAM() 以删除帐户并阻止后台注册重试。
从 SDK 注册通知
Intune应用 SDK 指南讨论了可能需要应用从 SDK 注册通知的几种方案,例如:
- 处理
WRONG_USER(的多标识应用请参阅 托管标识与非托管标识) - 处理
MANAGEMENT_REMOVED(的多标识应用请参阅 数据缓冲区保护) 。 - 处理或
WIPE_USER_AUXILIARY_DATA(的多标识应用WIPE_USER_DATA请参阅选择性擦除) 。 - 实现应用配置处理
REFRESH_APP_CONFIG的应用 (请参阅 从 SDK) 检索应用配置 。
本部分介绍 SDK 可以发送的每种类型的通知、应用程序何时以及为何要侦听它,以及如何实现通知接收器。
通知类型
所有 SDK 通知都实现 MAMNotification 接口,该接口具有返回 MAMNotificationType 枚举的单个函数 getType()。
大多数通知是 MAMUserNotification 实例,它们提供特定于单个标识的信息。 可以通过 函数检索 getUserOid() 标识的 OID,并通过 检索 getUserIdentity()标识的 UPN。
MAMEnrollmentNotification 和 MAMComplianceNotification 进一步扩展 MAMUserNotification了 ,分别包含尝试使用 MAM 服务注册用户或设备的结果,以及尝试修正应用保护 CA 符合性的结果。
| 通知类型 | 通知类 | 通知原因 | 适用性 | 处理提示 | 线程信息 |
|---|---|---|---|---|---|
COMPLIANCE_STATUS |
MAMComplianceNotification |
返回合规性修正尝试的结果。 | 实现应用保护 CA 的应用必须处理此问题。 | – | 不确定性 |
MAM_ENROLLMENT_RESULT |
MAMEnrollmentNotification |
返回注册尝试的结果。 | 所有应用都会收到此消息。 | – | 不确定性 |
MANAGEMENT_REMOVED |
MAMUserNotification |
应用即将变为非托管。 | 使用 MAMDataProtectionManager 的应用必须处理此问题。 |
请参阅 MANAGEMENT_REMOVED。 | 从不在 UI 线程上 |
REFRESH_APP_CONFIG |
MAMUserNotification |
应用配置值可能已更改。 | 实现应用配置和缓存应用配置数据的应用必须处理此问题。 | 应用必须使任何缓存的应用配置数据失效并刷新。 | 不确定性 |
REFRESH_POLICY |
MAMUserNotification |
应用保护策略可能已更改。 | 缓存应用保护策略的应用必须处理此问题。 | 应用必须使缓存的应用保护策略数据失效并更新。 | 不确定性 |
WIPE_USER_DATA |
MAMUserNotification |
擦除即将 (*) 发生。 | 使用 MAMDataProtectionManager 的应用必须处理此 或WIPE_USER_AUXILIARY_DATA 。 |
请参阅 选择性擦除。 | 从不在 UI 线程上 |
WIPE_USER_AUXILIARY_DATA |
MAMUserNotification |
擦除即将 (*) 发生。 | 只有多标识应用才会收到此消息。 使用 MAMDataProtectionManager 的应用必须处理此 或WIPE_USER_DATA 。 |
请参阅 选择性擦除。 | 从不在 UI 线程上 |
WIPE_COMPLETED |
MAMUserNotification |
擦除已完成。 | 对于所有应用都是可选的。 | 在 或 WIPE_USER_AUXILIARY_DATA之后WIPE_USER_DATA交付。如果应用从其擦除处理程序报告失败,则不会发送此通知。 |
从不在 UI 线程上 |
(*) 擦除的原因可能有多种,例如:
- 名为 unregisterAccountForMAM 的应用。
- IT 管理员启动了远程擦除。
- 不满足管理员要求的条件访问策略。
警告
应用不应同时注册 WIPE_USER_DATA 和 WIPE_USER_AUXILIARY_DATA 通知。
MANAGEMENT_REMOVED
通知 MANAGEMENT_REMOVED 通知应用以前由策略管理的帐户即将变为非托管帐户。
帐户不受管理后,应用无法再读取该帐户的加密文件、读取使用 MAMDataProtectionManager加密的帐户数据、与加密的剪贴板交互,或者无法以其他方式参与托管应用生态系统。
这不需要擦除用户数据或注销用户 (如果需要擦除, WIPE_USER_DATA 则会) 发送通知。
许多应用可能不需要处理此通知,但使用 MAMDataProtectionManager 的应用必须处理此通知。
有关详细信息 ,请参阅数据缓冲区保护 。
当 SDK 调用应用的 MANAGEMENT_REMOVED 接收器时,如下所示:
SDK 已将以前加密的文件解密 (但未受保护的数据缓冲区) 属于应用。 SD 卡上不直接属于应用 (位于公共位置的文件) 不会解密。
接收方方法创建的任何新文件或受保护数据缓冲区 (或接收方启动后运行的任何其他代码) 未加密。
应用仍有权访问加密密钥,因此解密数据缓冲区等作会成功。
应用接收方返回后,它不再有权访问加密密钥。
实现 MAMNotificationReceiver
若要从 SDK 注册通知,应用必须创建 MAMNotificationReceiver 并将其注册到 MAMNotificationReceiverRegistry。
若要注册接收方,请在方法中Application.onCreate调用registerReceiver接收方和所需的通知类型:
@Override
public void onCreate() {
super.onCreate();
MAMComponents.get(MAMNotificationReceiverRegistry.class)
.registerReceiver(
new ToastNotificationReceiver(),
MAMNotificationType.WIPE_USER_DATA);
}
应用的 MAMNotificationReceiver 实现必须包含 onReceive(MAMNotification notification) 方法。
此方法针对收到的每个通知单独调用,并且必须返回 boolean。
通常,此方法应始终返回 true,除非应用程序在响应通知时遇到失败。
与其他类型的 Android 接收器一样,应用程序在处理通知方面具有灵活性:
- 它可以为不同的通知类型创建不同的 MAMNotificationReceiver 实现。 在这种情况下,请确保分别注册每个实现和每个通知类型。
- 它可以使用单个 MAMNotificationReceiver 实现,其中包含用于响应多种不同通知类型的逻辑。 在这种情况下,必须为它可以响应的每种类型的通知注册它。
- 它可以创建多个 MAMNotificationReceiver 实现,每个实现都响应相同的通知类型。 在这种情况下,两者必须注册到相同的通知类型。
提示
可以安全地阻止, MAMNotificationReceiver.onReceive 因为其回调不会在 UI 线程上运行。
自定义主题
可以向 Intune App SDK 提供自定义主题;此自定义主题适用于所有 SDK 屏幕和对话框。 如果未提供主题,则使用默认 SDK 主题。
提供自定义主题
若要提供主题,请在 方法中添加以下代码 Application.onMAMCreate 行:
MAMThemeManager.setAppTheme(R.style.AppTheme);
在此示例中,将 替换为 R.style.AppTheme SDK 应应用的样式主题。
受信任的根证书管理
如果应用程序需要本地或专用证书颁发机构颁发的 SSL/TLS 证书来提供对内部网站和应用程序的安全访问,Intune App SDK 已使用 API 类 MAMTrustedRootCertsManager 和 MAMCertTrustWebViewClient 添加了对证书信任管理的支持。
注意
MAMCertTrustWebViewClient 支持 Android 10 或更高版本。
受信任的根证书管理支持:
- SSLContext
- SSLSocketFactory
- TrustManager
- WebView
要求
- 受信任的根证书管理需要为移动应用程序管理许可证Microsoft隧道。 若要了解详细信息,请访问: 使用移动应用程序管理Microsoft隧道。
- 配置Intune 应用程序配置策略,将受信任的根证书传递到 Android 上的业务线应用和 Microsoft Edge。 请参阅:将 Microsoft Tunnel VPN 用于未注册到 Microsoft Intune 的 Android 设备。
注意
受信任的根证书管理可以独立于Microsoft隧道VPN 网关使用,但必须许可Microsoft MAM Tunnel 使用。
使用来自Intune的受信任的根证书建立信任定位点
受信任的根证书管理允许你的应用将来自Intune的受信任的根证书与来自设备的证书结合使用。
如果设备的受信任根证书存储中不包含所需的受信任的根证书,则 MAMTrustsManager 和 MAMCertTrustWebViewClient 使用通过 应用程序配置 Policy 传递的Intune受信任的根证书作为回退选项。 这样,应用就可以使用设备和Intune证书来验证与受信任源的安全连接和通信。
为了增强其网络安全设置,应用可以使用网络安全配置 XML 文件。 受信任的根证书管理通过验证应用的网络安全配置 XML 是否具有以下任何功能来遵守此额外的安全性:
- 具有额外 CA(例如自签名证书)的自定义信任定位点。
- 用于限制受信任 CA 的特定于域的规则。
- 特定域的证书的固定集。
注意
有关 Android 网络安全配置的详细信息,请参阅 网络安全配置。
如果其中任何一项适用于正在检查信任的域,则受信任的根证书管理将跳过此域的自定义信任检查,只允许平台的默认信任管理器执行检查。
类 MAMTrustedRootCertsManager
此类提供以下 API:
-
createSSLContextForOID(String oid, String protocol):创建一个SSLContext对象,该对象对指定的标识和指定的 SSL/TLS 协议使用受信任的根证书。 此类返回SSLContext的对象已使用X509TrustManager来自设备和 MAM 服务的组合受信任的根证书的对象正确初始化。 -
createSSLSocketFactoryForOID(String oid, String protocol):创建一个SSLSocketFactory对象,该对象对指定的标识和指定的 SSL/TLS 协议使用受信任的根证书。 返回SSLSocketFactory的对象是从此类中的同一SSLContext对象引用的。 -
createX509TrustManagersForOID(String oid):创建一个对象数组X509TrustManager,这些对象使用来自设备和 MAM 服务的组合受信任的根证书作为指定标识。
注意
参数oid应为运行应用程序的特定用户 (OID) Microsoft Entra用户 ID。 如果用户标识符事先未知,则可以传递 值 null ,并且 MAM 会尝试从调用这些 API 的线程或进程中发现正确的标识。 必须在进程或线程上正确设置标识,MAM 才能发现标识。 有关在进程或线程上设置活动标识的详细信息,请参阅 阶段 5:多标识。
注意
protocol如果未提供 参数,平台将使用受支持的最高 SSL/TLS 协议。
下面是使用此类的一些示例。
使用 HttpsUrlConnection 的示例
// Create an SSL socket factory using supplying the optional parameters identity and protocol
SSLSocketFactory sslSocketFactory = MAMTrustedRootCertsManager.createSSLSocketFactoryForOID(oid, "TLSv1.3");
// Create a URL object for the desired endpoint
URL url = new URL("https://example.com");
// Open a connection using the URL object
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
// Set the SSL socket factory for the connection
httpsURLConnection.setSSLSocketFactory(sslSocketFactory);
// Perform any other configuration or operations on the connection as needed
...
使用 OkHttpClient 的示例
// Get the TrustManager instances for an identity from the SDK
TrustManager[] trustManagers = MAMTrustedRootCertsManager.createX509TrustManagersForOID(oid);
// Get SSLContext from the platform
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
// Initialize the SSLContext with the trust managers from the Intune App SDK
sslContext.init(null, trustManagers, null);
// Create an OkHttpClient.Builder object
OkHttpClient.Builder builder = new OkHttpClient.Builder();
// Set the SSLSocketFactory and the trust managers from the SDK
builder.sslSocketFactory(sslContext.socketFactory, trustManagers[0] as X509TrustManager).build();
// Build an OkHttpClient object from the builder
OkHttpClient okHttpClient = builder.build();
// Create a Request object for the desired endpoint
Request request = new Request.Builder().url("https://example.com").build();
// Execute the request using the OkHttpClient object and get a Response object
Response response = okHttpClient.newCall(request).execute();
// Perform any other operations on the response as needed
...
类 MAMCertTrustWebViewClient
此类提供 Android 类 android.webkit.WebViewClient的自定义实现。 类提供了一种处理 中的 WebViewSSL 错误android.net.http.SslError.SSL_UNTRUSTED的方法。
处理错误时,类使用Intune配置的、MAM 服务提供的受信任的根证书。 此方法从中生成 SSL 错误 WebView的目标 URL 检查主机的可信度。 如果自定义实现不处理 SSL 错误,则系统会调用从超类继承的默认行为。
使用此类时,请创建它的实例,然后调用 WebView.setWebViewClient(WebViewClient) 以将其注册到 WebView 实例。
下面是使用此类的示例。
使用 WebView 的示例
// Get the MAM implementation of WebViewClient from the Intune App SDK
MAMCertTrustWebViewClient mamCertTrustWebViewClient = new MAMCertTrustWebViewClient();
// Set the MAM WebViewClient from the SDK as the current handler on the instance of WebView
webView.setWebViewClient(mamCertTrustWebViewClient);
// Perform any other operations on WebView
...
退出条件
有关详细信息,请参阅 使用更改策略进行快速测试 ,以便于测试。
验证保存到限制和从中打开
如果未实现 限制应用与设备或云存储位置之间的数据传输的策略,请跳过此部分。
重新熟悉应用可以将数据保存到云服务或本地数据以及从云服务或本地数据打开数据的每一种方案。
为简单起见,这些测试假定你的应用仅支持从应用中的单个位置保存到 OneDrive 和从 OneDrive 打开数据。 但是,你必须验证每个组合:针对应用允许保存数据的每个位置的每个受支持的保存位置,以及针对应用允许打开数据的每个位置的每个受支持的打开位置。
对于这些测试,请在开始测试之前安装应用和Intune 公司门户;使用托管帐户登录。 此外:
- 将托管帐户的策略设置为:
- “将组织数据发送到其他应用”设置为“策略托管应用”。
- “从其他应用接收数据”设置为“策略托管应用”。
| 应用场景 | 前提 条件 | 步骤 |
|---|---|---|
| 保存到,完全允许 | “保存组织数据的副本”策略设置为“允许” | - 导航到可将数据保存到 OneDrive 的应用部分。 - 尝试使用登录到应用的同一托管帐户将文档保存到 OneDrive。 - 确认是否允许保存。 |
| 保存到,豁免 | - “保存组织数据的副本”策略设置为“阻止” - “允许用户将副本保存到所选服务”策略设置为“仅限 OneDrive ” |
- 导航到可将数据保存到 OneDrive 的应用部分。 - 尝试使用登录到应用的同一托管帐户将文档保存到 OneDrive。 - 确认是否允许保存。 - 如果应用允许,请尝试将文件保存到其他云存储位置,并确认它已被阻止。 |
| 保存到,已阻止 | “保存组织数据的副本”策略设置为“阻止” | - 导航到可将数据保存到 OneDrive 的应用部分。 - 尝试使用登录到应用的同一托管帐户将文档保存到 OneDrive。 - 确认已阻止保存。 - 如果应用允许,请尝试将文件保存到其他云存储位置,并确认它已被阻止。 |
| 打开自,完全允许 | “将数据打开组织文档”策略设置为“允许” | - 导航到应用可从 OneDrive 打开数据的部分。 - 尝试使用登录到应用存储的同一托管帐户从 OneDrive 打开文档。 - 确认是否允许打开。 |
| 打开自,已免除 | - “将数据打开到组织文档中”策略设置为“阻止” - “允许用户从所选服务打开数据”策略设置为“仅限 OneDrive ” |
- 导航到应用可从 OneDrive 打开数据的部分。 - 尝试使用登录到应用存储的同一托管帐户从 OneDrive 打开文档。 - 确认是否允许打开。 - 如果应用允许,请尝试从其他云存储位置打开另一个文件,并确认它已被阻止。 |
| 打开自,已阻止 | “将数据打开到组织文档中”策略设置为“阻止” | - 导航到应用可从 OneDrive 打开数据的部分。 - 尝试使用登录到应用存储的同一托管帐户从 OneDrive 打开文档。 - 确认打开已阻止。 - 如果应用允许,请尝试从其他云存储位置打开另一个文件,并确认它已被阻止。 |
验证通知限制
如果未实现 限制通知内内容的策略,请跳过此部分。
就应用保护策略而言,应用程序可能会触发三种不同类型的通知:
- 不包含任何帐户数据的通知。
- 包含属于托管帐户的数据的通知。
- 包含属于非托管帐户的数据的通知。
如果应用程序是单一标识,则只有前两个标识相关,因为如果唯一的帐户是非托管帐户,则不会应用任何保护。
可以通过触发配置了不同策略值的所有三种类型的通知来验证通知限制。
对于这些测试,请在开始测试之前安装应用和Intune 公司门户;使用托管帐户登录。 如果你的应用是多标识的,则还要使用非托管帐户登录到你的应用。
| 应用场景 | 前提 条件 | 步骤 |
|---|---|---|
| 阻止完整内容 | “组织数据通知”策略设置为“阻止” | - 触发应用以触发没有帐户数据的通知。 - 确认通知未显示任何内容。 - 触发应用以使用托管帐户的数据触发通知。 - 确认通知未显示任何内容。 - 触发应用以使用非托管帐户的数据触发通知。 - 确认通知未显示任何内容。 |
| 部分内容被阻止 | “组织数据通知”策略设置为“阻止组织数据” | - 触发应用以触发没有帐户数据的通知。 - 确认通知显示其完整内容。 - 触发应用以使用托管帐户的数据触发通知。 - 确认通知对托管帐户的内容进行修订。 - 触发应用以使用非托管帐户的数据触发通知。 - 确认通知显示其完整内容。 |
| 未阻止任何内容 | “组织数据通知”策略设置为“允许” | - 触发应用以触发没有帐户数据的通知。 - 确认通知显示其完整内容。 - 触发应用以使用托管帐户的数据触发通知。 - 确认通知显示其完整内容。 - 触发应用以使用非托管帐户的数据触发通知。 - 确认通知显示其完整内容。 |
验证数据备份和还原
如果未实现 用于保护备份数据的策略,请跳过此部分。
使用应用为备份配置的内容 (文件和键值对) 重新熟悉自己。 应验证是否只有预期的内容是还原的一部分。 还原中的额外内容可能会导致数据泄漏。
对于这些测试,请安装应用和Intune 公司门户;在开始测试之前使用托管帐户登录。 如果你的应用是多标识的,则还要使用非托管帐户登录到应用。
按照 Android 的官方说明测试备份。 这些说明与自动备份和键/值备份不同,因此请密切关注它们。
根据策略验证自定义屏幕捕获
如果未实现 自定义屏幕捕获限制,请跳过此部分。
如果应用程序具有绕过 Android Window级别 FLAG_SECURE的功能,请验证此功能是否被应用保护策略屏幕捕获限制阻止。
对于这些测试,请在开始测试之前安装应用和Intune 公司门户;使用托管帐户登录。
| 应用场景 | 前提 条件 | 步骤 |
|---|---|---|
| 屏幕捕获已阻止 | “屏幕捕获和 Google 助手”策略设置为“阻止” | - 导航到使用自定义 FLAG_SECURE 代码的应用部分。- 尝试使用该功能。 - 确认该功能被阻止。 |
| 允许的屏幕捕获 | 将“屏幕捕获和 Google 助手”策略设置为“允许” | - 导航到使用自定义 FLAG_SECURE 代码的应用部分。- 尝试使用该功能。 - 确认是否允许该功能。 |
验证应用保护 CA
如果未实现 支持应用保护 CA,请跳过此部分。
除了创建应用保护策略并将其分配给应用和测试帐户的典型验证步骤外,还必须创建应用保护条件访问策略并将其分配给测试帐户。 有关详细信息,请参阅使用Intune设置基于应用的条件访问策略。
测试步骤:
- 在开始此测试之前,请卸载Microsoft Authenticator 并Intune 公司门户。
- 安装应用。
- 使用面向应用保护策略和基于应用的 CA 策略的测试帐户登录到应用。
- 确认应用提示你安装公司门户。
- 再次登录。
- 确认应用提示你注册设备。 按照提示作。 如果应用未在此处提示注册,请首先确认测试设备已卸载其他启用了 SDK 的应用、公司门户和 Authenticator。 如果这仍然没有提示,请重新访问实现说明。
- 确认可以在注册后访问所有应用数据。
验证通知接收器
如果未实现 从 SDK 注册通知,请跳过此部分。
验证步骤取决于应用注册的通知类型。 对于所有类型的通知,请添加日志记录以确保正确调用接收方。
MAM_ENROLLMENT_RESULT 可以通过使用应用保护策略所面向的帐户登录到应用程序来触发。
可以通过更新面向测试帐户的相应应用程序配置策略和应用保护策略并等待 SDK 接收更新的策略来触发 REFRESH_APP_CONFIGREFRESH_POLICY 和 。
提示
请参阅 使用更改策略快速测试 以加快此过程。
可以通过从Microsoft Intune发出选择性擦除来触发 MANAGEMENT_REMOVEDWIPE_USER_DATA、、 WIPE_USER_AUXILIARY_DATA和 WIPE_COMPLETED 通知。
验证自定义主题
如果未实现 自定义主题,请跳过此部分。
可以通过检查 SDK 对话框上的颜色来验证自定义主题支持。 检查最简单的对话框是 MAM PIN 屏幕。
前提 条件:
- 将托管帐户的策略设置为:
- 将“用于访问的 PIN”设置为“必需”。
- 安装应用和Intune 公司门户。
测试步骤:
- 启动应用程序并使用测试帐户登录。
- 确认“MAM PIN”屏幕已显示,其主题基于你提供给 SDK 的自定义主题。
后续步骤
如果你按顺序遵循了本指南并完成了本文前面的所有退出条件,则你的应用现在已与 Intune 应用 SDK 完全集成,并且可以强制实施应用保护策略。 如果跳过了前面的应用参与部分之一:阶段 5:多标识和阶段 6:应用程序配置,并且不确定应用是否应支持这些功能,请重新访问 SDK 集成的关键决策。
应用保护现在是应用的核心方案。 继续开发应用时,请继续参考本指南和 附录 。