Microsoft Intune App SDK for Android 開發人員指南Microsoft Intune App SDK for Android developer guide

注意

您可能想要先閱讀 Intune App SDK 概觀,其中涵蓋 SDK 目前的功能,並說明如何在每個支援的平台上進行整合準備。You might want to first read the Intune App SDK overview, which covers the current features of the SDK and describes how to prepare for integration on each supported platform.

Microsoft Intune App SDK for Android 可讓您將 Intune 應用程式保護原則 (也稱為 APP 或 MAM 原則) 併入原生 Android 應用程式中。The Microsoft Intune App SDK for Android lets you incorporate Intune app protection policies (also known as APP or MAM policies) into your native Android app. 「可搭配 Intune 的應用程式」是與 Intune App SDK 整合的應用程式。An Intune-enlightened application is one that is integrated with the Intune App SDK. Intune 系統管理員可在 Intune 主動管理應用程式時,輕鬆地將應用程式保護原則部署至可搭配 Intune 的應用程式。Intune administrators can easily deploy app protection policies to your Intune-enlightened app when Intune actively manages the app.

SDK 的功能What's in the SDK

Intune App SDK 包含下列檔案:The Intune App SDK consists of the following files:

  • Microsoft.Intune.MAM.SDK.aar:SDK 元件 (Support.V4 和 Support.V7 JAR 檔案除外)。Microsoft.Intune.MAM.SDK.aar: The SDK components, with the exception of the Support.V4 and Support.V7 JAR files. 如果您的建置系統支援 AAR 檔案,則可以使用這個檔案來取代個別的元件。This file can be used in place of the individual components if your build system supports AAR files.
  • Microsoft.Intune.MAM.SDK.Support.v4.jar:在使用 Android v4 支援程式庫的應用程式中啟用 MAM 所需的介面。Microsoft.Intune.MAM.SDK.Support.v4.jar: The interfaces necessary to enable MAM in apps that use the Android v4 support library. 需要這項支援的應用程式必須直接參考 JAR 檔案。Apps that need this support must reference the JAR file directly.
  • Microsoft.Intune.MAM.SDK.Support.v7.jar:在使用 Android v7 支援程式庫的應用程式中啟用 MAM 所需的介面。Microsoft.Intune.MAM.SDK.Support.v7.jar: The interfaces necessary to enable MAM in apps that use the Android v7 support library. 需要這項支援的應用程式必須直接參考 JAR 檔案。Apps that need this support must reference the JAR file directly.
  • proguard.txt:包含使用 ProGuard 進行建置時必須套用的 ProGuard 規則。proguard.txt: Contains ProGuard rules which must be applied if building with ProGuard.
  • CHANGELOG.txt:提供每個 SDK 版本中的變更記錄。CHANGELOG.txt: Provides a record of changes made in each SDK version.
  • THIRDPARTYNOTICES.TXT:確認將會編譯至應用程式中的協力廠商及/或 OSS 程式碼的屬性通知。THIRDPARTYNOTICES.TXT: An attribution notice that acknowledges third-party and/or OSS code that will be compiled into your app.

如果您的建置系統不支援 AAR 檔案,則可以使用下列檔案取代 Microsoft.Intune.MAM.SDK.aar。If your build system does not support AAR files, you may use the following files in place of Microsoft.Intune.MAM.SDK.aar.

  • Microsoft.Intune.MAM.SDK.jar:啟用 MAM 並與 Intune 公司入口網站應用程式互通所需的介面。Microsoft.Intune.MAM.SDK.jar: The interfaces necessary to enable MAM and interoperability with the Intune Company Portal app. 應用程式必須將其指定為 Android 程式庫參考。Apps must specify it as an Android library reference.
  • 資源目錄:SDK 所依賴的資源 (例如字串)。The res directory: The resources (like strings) on which the SDK relies.
  • AndroidManifest.xml:進入點和程式庫需求。AndroidManifest.xml: Entry points and the library requirements.

需求Requirements

Intune App SDK 是一種編譯過的 Android 專案。The Intune App SDK is a compiled Android project. 因此,它基本上不會受到應用程式針對其最低或目標 API 版本使用的 Android 版本所影響。As a result, it is largely unaffected by the version of Android that the app uses for its minimum or target API versions. 此 SDK 支援 Android API 14 (Android 4.0+) 到 Android API 25 (Android 7.1)。The SDK supports Android API 14 (Android 4.0+) through Android API 25 (Android 7.1).

公司入口網站應用程式Company Portal app

Intune App SDK for Android 必須仰賴裝置上的公司入口網站應用程式來啟用應用程式保護原則。The Intune App SDK for Android relies on the presence of the Company Portal app on the device to enable app protection policies. 公司入口網站會從 Intune 服務擷取應用程式保護原則。The Company Portal retrieves app protection policies from the Intune service. 應用程式初始化時,它會載入原則和程式碼,以從公司入口網站強制執行該原則。When the app initializes, it loads policy and code to enforce that policy from the Company Portal.

注意

當裝置上沒有公司入口網站應用程式時,可搭配 Intune 的應用程式會具有和不支援 Intune 應用程式保護原則的一般應用程式相同的行為。When the Company Portal app is not on the device, an Intune-enlightened app behaves the same as a normal app that does not support Intune app protection policies.

對於沒有裝置註冊的應用程式保護,使用者「不」_需要使用公司入口網站應用程式註冊裝置。For app protection without device enrollment, the user is not_ required to enroll the device by using the Company Portal app.

SDK 整合SDK Integration

組建整合Build integration

Intune App SDK 是不含外部相依性的標準 Android 程式庫。The Intune App SDK is a standard Android library with no external dependencies. Microsoft.Intune.MAM.SDK.jar 包含啟用應用程式保護原則所需的介面,以及和 Microsoft Intune 公司入口網站應用程式互通所需的程式碼。Microsoft.Intune.MAM.SDK.jar contains both the interfaces necessary for an app protection policy enablement and the code necessary to interoperate with the Microsoft Intune Company Portal app.

Microsoft.Intune.MAM.SDK.jar 必須指定為 Android 程式庫參考。Microsoft.Intune.MAM.SDK.jar must be specified as an Android library reference. 若要這麼做,請在 Android Studio 中開啟應用程式專案,然後移至 [檔案] > [新增] > [新模組],然後選取 [匯入 .JAR/.AAR 套件]。To do this, open your app project in Android Studio and go to File > New > New module and select Import .JAR/.AAR Package. 請選取我們的 Android 封存套件,Microsoft.Intune.MAM.SDK.aar。Select our Android archive package Microsoft.Intune.MAM.SDK.aar.

此外,Microsoft.Intune.MAM.SDK.Support.v4Microsoft.Intune.MAM.SDK.Support.v7 皆個別包含 android.support.v4android.support.v7 的 Intune 版本。Additionally, Microsoft.Intune.MAM.SDK.Support.v4 and Microsoft.Intune.MAM.SDK.Support.v7 contain Intune variants of android.support.v4 and android.support.v7 respectively. 它們並沒有內建於 Microsoft.Intune.MAM.SDK.aar 之內,以防應用程式並不想要包含支援程式庫。They are not built into Microsoft.Intune.MAM.SDK.aar in case an app does not want to include the support libraries. 它們是標準 JAR 檔案,而非 Android 程式庫專案。They are standard JAR files instead of Android library projects.

ProGuardProGuard

若使用 ProGuard (英文) (或任何其他壓縮/混淆機制) 做為建置步驟,便必須排除 Intune SDK 類別。If ProGuard (or any other shrinking/obfuscation mechanism) is used as a build step, Intune SDK classes must be excluded. 針對 ProGuard,這可以透過包含隨附於 SDK 之 proguard.txt 中的規則來達成。For ProGuard, this can be accomplished by including the rules from the proguard.txt file distributed with the SDK.

Azure Active Directory Authentication Library (ADAL) 可能會有屬於自己的 ProGuard 限制。The Azure Active Directory Authentication Libraries (ADAL) may have its own ProGuard restrictions. 如果應用程式整合了 ADAL,則您必須遵循這些限制的相關 ADAL 文件。If your app integrates ADAL, you must follow the ADAL documentation on these restrictions.

進入點Entry points

Azure Active Directory 驗證程式庫 (ADAL) 需要這些權限才能執行代理驗證。The Azure Active Directory Authentication Library (ADAL) requires these permissions to perform brokered authentication. 如果未將這些權限授與應用程式或使用者已撤銷這些權限,則會停用需要訊息代理程式 (公司入口網站應用程式) 的驗證流程。If these permissions are not granted to the app or are revoked by the user, authentication flows that require the broker (the Company Portal app) will be disabled.

Intune App SDK 需要變更應用程式的原始程式碼,以啟用 Intune 應用程式保護原則。The Intune App SDK requires changes to an app's source code to enable Intune app protection policies. 這是透過將 Android 基底類別取代為對等的 Intune 基底類別來完成,其名稱前面會加上 MAMThis is done through the replacement of the Android base classes with equivalent Intune base classes, whose names have the prefix MAM. SDK 類別的位置介於 Android 基底類別和應用程式本身針對該類別的衍生版本之間。The SDK classes live between the Android base class and the app's own derived version of that class. 以活動為範例來看,最後您得到的繼承階層會像這樣:Activity > MAMActivity > AppSpecificActivityUsing an activity as an example, you end up with an inheritance hierarchy that looks like: Activity > MAMActivity > AppSpecificActivity.

例如,當 AppSpecificActivity 與父系互動 (例如,呼叫 super.onCreate()) 時,MAMActivity 是超級類別。For example, when AppSpecificActivity interacts with its parent (for example, calling super.onCreate()), MAMActivity is the super class.

一般而言,Android 應用程式擁有單一模式,並可透過其 Context (英文) 物件存取系統。Typical Android apps have a single mode and can access the system through their Context object. 另一方面,已經和 Intune App SDK 整合的應用程式則具有雙重模式。Apps that have integrated the Intune App SDK, on the other hand, have dual modes. 這些應用程式可以繼續透過 Context 物件存取系統。These apps continue to access the system through the Context object. 根據所使用的基底 ActivityContext 物件將由 Android 提供,或在系統的限制檢視和 Android 提供的 Context 之間,以智慧的方式進行多工處理。Depending on the base Activity used, the Context object will be provided by Android or will intelligently multiplex between a restricted view of the system and the Android-provided Context. 在您從其中一個 MAM 進入點進行衍生之後,就可以用正常方式安全地使用 Context,例如用來啟動 Activity 類別和使用 PackageManagerAfter you derive from one of the MAM entry points, it's safe to use Context as you would normally -- for example, starting Activity classes and using PackageManager.

將類別、方法和活動取代為其 MAM 對等項目Replace classes, methods, and activities with their MAM equivalent

您必須將 Android 基底類別取代為其各自的 MAM 對等項目。Android base classes must be replaced with their respective MAM equivalents. 若要這樣做,請找到下表所列類別的所有執行個體,並取代為 Intune App SDK 對等項目。To do so, find all instances of the classes listed in the following table and replace them with the Intune App SDK equivalent.

Android 基底類別Android base class Intune App SDK 取代Intune App SDK replacement
android.app.Activityandroid.app.Activity MAMActivityMAMActivity
android.app.ActivityGroupandroid.app.ActivityGroup MAMActivityGroupMAMActivityGroup
android.app.AliasActivityandroid.app.AliasActivity MAMAliasActivityMAMAliasActivity
android.app.Applicationandroid.app.Application MAMApplicationMAMApplication
android.app.DialogFragmentandroid.app.DialogFragment MAMDialogFragmentMAMDialogFragment
android.app.ExpandableListActivityandroid.app.ExpandableListActivity MAMExpandableListActivityMAMExpandableListActivity
android.app.Fragmentandroid.app.Fragment MAMFragmentMAMFragment
android.app.IntentServiceandroid.app.IntentService MAMIntentServiceMAMIntentService
android.app.LauncherActivityandroid.app.LauncherActivity MAMLauncherActivityMAMLauncherActivity
android.app.ListActivityandroid.app.ListActivity MAMListActivityMAMListActivity
android.app.NativeActivityandroid.app.NativeActivity MAMNativeActivityMAMNativeActivity
android.app.PendingIntentandroid.app.PendingIntent MAMPendingIntent (請參閱下列附註)MAMPendingIntent (see notes below)
android.app.Serviceandroid.app.Service MAMServiceMAMService
android.app.TabActivityandroid.app.TabActivity MAMTabActivityMAMTabActivity
android.app.TaskStackBuilderandroid.app.TaskStackBuilder MAMTaskStackBuilderMAMTaskStackBuilder
android.app.backup.BackupAgentandroid.app.backup.BackupAgent MAMBackupAgentMAMBackupAgent
android.app.backup.BackupAgentHelperandroid.app.backup.BackupAgentHelper MAMBackupAgentHelperMAMBackupAgentHelper
android.app.backup.FileBackupHelperandroid.app.backup.FileBackupHelper MAMFileBackupHelperMAMFileBackupHelper
android.app.backup.SharePreferencesBackupHelperandroid.app.backup.SharePreferencesBackupHelper MAMSharedPreferencesBackupHelperMAMSharedPreferencesBackupHelper
android.content.BroadcastReceiverandroid.content.BroadcastReceiver MAMBroadcastReceiverMAMBroadcastReceiver
android.content.ContentProviderandroid.content.ContentProvider MAMContentProviderMAMContentProvider
android.os.Binderandroid.os.Binder MAMBinder (只有在 Binder 不是從 Android Interface Definition Language (AIDL) 介面產生時才需要)MAMBinder (Only necessary if the Binder is not generated from an Android Interface Definition Language (AIDL) interface)
android.provider.DocumentsProviderandroid.provider.DocumentsProvider MAMDocumentsProviderMAMDocumentsProvider
android.preference.PreferenceActivityandroid.preference.PreferenceActivity MAMPreferenceActivityMAMPreferenceActivity

Microsoft.Intune.MAM.SDK.Support.v4.jar:Microsoft.Intune.MAM.SDK.Support.v4.jar:

Android 類別 Intune MAMAndroid Class Intune MAM Intune App SDK 取代Intune App SDK replacement
android.support.v4.app.DialogFragmentandroid.support.v4.app.DialogFragment MAMDialogFragmentMAMDialogFragment
android.support.v4.app.FragmentActivityandroid.support.v4.app.FragmentActivity MAMFragmentActivityMAMFragmentActivity
android.support.v4.app.Fragmentandroid.support.v4.app.Fragment MAMFragmentMAMFragment
android.support.v4.app.TaskStackBuilderandroid.support.v4.app.TaskStackBuilder MAMTaskStackBuilderMAMTaskStackBuilder
android.support.v4.content.FileProviderandroid.support.v4.content.FileProvider MAMFileProviderMAMFileProvider

Microsoft.Intune.MAM.SDK.Support.v7.jar:Microsoft.Intune.MAM.SDK.Support.v7.jar:

Android 類別Android Class Intune App SDK 取代Intune App SDK replacement
android.support.v7.app.ActionBarActivityandroid.support.v7.app.ActionBarActivity MAMActionBarActivityMAMActionBarActivity

重新命名的方法Renamed Methods

在許多情況下,Android 類別中可用的方法已在 MAM 取代類別中被標示為完稿。In many cases, a method available in the Android class has been marked as final in the MAM replacement class. 在此情況下,MAM 取代類別會提供您應該覆寫的類似具名方法 (通常後置字元為 MAM)。In this case, the MAM replacement class provides a similarly named method (generally suffixed with MAM) that you should override instead. 例如,當衍生自 MAMActivity,而不是覆寫 onCreate() 然後呼叫 super.onCreate() 時,Activity 必須覆寫 onMAMCreate() 並呼叫 super.onMAMCreate()For example, when deriving from MAMActivity, instead of overriding onCreate() and calling super.onCreate(), Activity must override onMAMCreate() and call super.onMAMCreate(). Java 編譯器應該強制執行完稿的限制,以防止意外覆寫原始的方法,而不是 MAM 對等項目。The Java compiler should enforce the final restrictions to prevent accidental override of the original method instead of the MAM equivalent.

PendingIntentPendingIntent

您必須使用 MAMPendingIntent.get* 方法,而不是 PendingIntent.get*Instead of PendingIntent.get*, you must use the MAMPendingIntent.get* method. 之後,您可以像往常一樣使用結果 PendingIntentAfter this, you can use the resultant PendingIntent as usual.

資訊清單取代Manifest Replacements

請注意,您可能需要在資訊清單及 Java 程式碼中執行部分上述類別取代。Please note that it may be necessary to perform some of the above class replacements in the manifest as well as in Java code. 特殊注意事項:Of special note:

  • 針對 android.support.v4.content.FileProvider 的資訊清單參考,必須以 com.microsoft.intune.mam.client.support.v4.content.MAMFileProvider 取代。Manifest references to android.support.v4.content.FileProvider must be replaced with com.microsoft.intune.mam.client.support.v4.content.MAMFileProvider.
  • 如果您的應用程式不需要自己的衍生應用程式類別,com.microsoft.intune.mam.client.app.MAMApplication 必須設定為資訊清單所用的應用程式類別名稱。If your application does not have a need for its own derived Application class, com.microsoft.intune.mam.client.app.MAMApplication must be set as the name of the Application class used in the manifest.

SDK 權限SDK permissions

Intune App SDK 需要在與其整合的應用程式上,具有三個 Android 系統權限The Intune App SDK requires three Android system permissions on apps that integrate it:

  • android.permission.GET_ACCOUNTS (如有需要,則會在執行階段要求)android.permission.GET_ACCOUNTS (requested at runtime if required)

  • android.permission.MANAGE_ACCOUNTS

  • android.permission.USE_CREDENTIALS

Azure Active Directory 驗證程式庫 (ADAL) 需要這些權限才能執行代理驗證。The Azure Active Directory Authentication Library (ADAL) requires these permissions to perform brokered authentication. 如果未將這些權限授與應用程式或使用者已撤銷這些權限,則會停用需要訊息代理程式 (公司入口網站應用程式) 的驗證流程。If these permissions are not granted to the app or are revoked by the user, authentication flows that require the broker (the Company Portal app) will be disabled.

記錄Logging

記錄應該要盡早初始化,以取得最豐富的記錄資料。Logging should be initialized early to get the most value out of logged data. Application.onMAMCreate() 通常是初始化記錄的最佳位置。Application.onMAMCreate() is typically the best place to initialize logging.

若要在應用程式中接收 MAM 記錄,請建立 Java 處理常式 (英文) 並將它新增至 MAMLogHandlerWrapperTo receive MAM logs in your app, create a Java Handler and add it to the MAMLogHandlerWrapper. 這將會針對每個記錄訊息在應用程式處理常式上叫用 publish()This will invoke publish() on the application handler for every log message.

/**
 * Global log handler that enables fine grained PII filtering within MAM logs.  
 *
 * To start using this you should build your own log handler and add it via
 * MAMComponents.get(MAMLogHandlerWrapper.class).addHandler(myHandler, false);  
 *
 * You may also remove the handler entirely via
 * MAMComponents.get(MAMLogHandlerWrapper.class).removeHandler(myHandler);
 */
public interface MAMLogHandlerWrapper {
    /**
     * Add a handler, PII can be toggled.
     *
     * @param handler handler to add.
     * @param wantsPII if PII is desired in the logs.    
     */
    void addHandler(final Handler handler, final boolean wantsPII);

    /**
     * Remove a handler.
     *
     * @param handler handler to remove.
     */
    void removeHandler(final Handler handler);
}

啟用需要應用程式參與的功能Enable features that require app participation

有數個 SDK 無法自行實作的應用程式保護原則。There are several app protection policies the SDK cannot implement on its own. 此應用程式可控制其行為,以使用可在以下 AppPolicy 介面中找到的數個 API,實現這些功能。The app can control its behavior to achieve these features by using several APIs that you can find in the following AppPolicy interface. 若要擷取 AppPolicy 執行個體,請使用 MAMPolicyManager.getPolicyTo retrieve an AppPolicy instance, use MAMPolicyManager.getPolicy.

/**
 * External facing application policies.
 */
public interface AppPolicy {

/**
 * Restrict where an app can save personal data.
 * This function is now deprecated. Please use getIsSaveToLocationAllowed(SaveLocation, String) instead
 * @return True if the app is allowed to save to personal data stores; false otherwise.
 */
@Deprecated
boolean getIsSaveToPersonalAllowed();

/**
 * Check if policy prohibits saving to a content provider location.
 *
 * @param location
 *            a content URI to check
 * @return True if location is not a content URI or if policy does not prohibit saving to the content location.
 */
boolean getIsSaveToLocationAllowed(Uri location);

/**
 * Determines if the SaveLocation passed in can be saved to by the username associated with the cloud service.
 *
 * @param service
 *           see {@link SaveLocation}.
 * @param username
 *           the username/email associated with the cloud service being saved to. Use null if a mapping between
 *           the AAD username and the cloud service username does not exist or the username is not known.
 * @return true if the location can be saved to by the identity, false if otherwise.
 */
boolean getIsSaveToLocationAllowed(SaveLocation service, String username);

/**
 * Whether the SDK PIN prompt is enabled for the app.
 *
 * @return True if the PIN is enabled. False otherwise.
 */
boolean getIsPinRequired();

/**
 * Whether the Intune Managed Browser is required to open web links.
 * @return True if the Managed Browser is required, false otherwise
 */
boolean getIsManagedBrowserRequired();

/**
 * Check if policy allows Contact sync to local contact list.
 *
 * @return True if Contact sync is allowed to save to local contact list; false otherwise.
 */
boolean getIsContactSyncAllowed();

/**
 * Return the policy in string format to the app.
 *  
 * @return The string representing the policy.
 */
String toString();

}

注意

MAMPolicyManager.getPolicy 一律會傳回非 null 的應用程式原則,即使裝置或應用程式不受 Intune 管理原則限制,亦是如此。MAMPolicyManager.getPolicy will always return a non-null App Policy, even if the device or app is not under an Intune management policy.

範例:判斷應用程式是否需要 PINExample: Determine if PIN is required for the app

在 IT 系統管理員已設定 SDK 以提示輸入應用程式 PIN 的情況下,如果應用程式有屬於自己的 PIN 使用者體驗,您可能會想要停用它。If the app has its own PIN user experience, you might want to disable it if the IT administrator has configured the SDK to prompt for an app PIN. 若要判斷 IT 系統管理員是否已將應用程式 PIN 原則部署至此應用程式,請針對目前的使用者呼叫下列方法:To determine if the IT administrator has deployed the app PIN policy to this app, for the current end user, call the following method:

MAMComponents.get(AppPolicy.class).getIsPinRequired();

範例:判斷主要 Intune 使用者Example: Determine the primary Intune user

除了在 AppPolicy 中公開的 API 之外,使用者主體名稱 (UPN) 也會由在MAMUserInfo 中定義的 getPrimaryUser() API 公開。In addition to the APIs exposed in AppPolicy, the user principal name (UPN) is also exposed by the getPrimaryUser() API defined inside the MAMUserInfo interface. 若要取得 UPN,請呼叫下列項目:To get the UPN, call the following:

MAMUserInfo info = MAMComponents.get(MAMUserInfo.class);
if (info != null) return info.getPrimaryUser();

MAMUserInfo 介面的完整定義如下:The full definition of the MAMUserInfo interface is below:

/**
 * External facing user informations.
 *
 */
public interface MAMUserInfo {
       /**
        * Get the primary user name.
        *
        * @return the primary user name or null if the device is not enrolled.
        */
       String getPrimaryUser();
}

範例:判斷是否允許儲存至裝置或雲端儲存體Example: Determine if saving to device or cloud storage is permitted

許多應用程式實作功能,可讓使用者將檔案儲存於本機或儲存至雲端儲存體服務。Many apps implement features that allow the end user to save files locally or to a cloud storage service. Intune App SDK 可讓 IT 系統管理員套用組織適用的原則限制,以防資料外洩。The Intune App SDK allows IT administrators to protect against data leakage by applying policy restrictions as they see fit in their organization. IT 人員可以控制的其中一項原則是,使用者是否可以儲存至未受管理的「個人」資料存放區。One of the policies that IT can control is whether the end user can save to a "personal," unmanaged data store. 這包括儲存至本機位置、SD 記憶卡或協力廠商備份服務。This includes saving to a local location, SD card, or third-party backup services.

啟用此功能需要應用程式參與。App participation is needed to enable the feature. 如果您的應用程式可直接從應用程式儲存至個人或雲端位置,您就必須實作此功能,以確保 IT 系統管理員能控制是否允許儲存至某個位置。If your app allows saving to personal or cloud locations directly from the app, you must implement this feature to ensure that the IT administrator can control whether saving to a location is allowed. 下列 API 可讓應用程式知道目前的 Intune 系統管理員原則是否允許儲存到個人存放區。The API below lets the app know whether saving to a personal store is allowed by the current Intune administrator's policy. 接著,應用程式即可強制執行原則,因為它會感知使用者透過應用程式可使用的個人資料存放區。The app can then enforce the policy, since it is aware of personal data store available to the end user through the app.

若要判斷是否已強制執行該原則,請進行下列呼叫:To determine if the policy is enforced, make the following call:

MAMComponents.get(AppPolicy.class).getIsSaveToLocationAllowed(
SaveLocation service, String username);

其中 service 為下列其中一個 SaveLocations:... where service is one of the following SaveLocations:

* <span data-ttu-id="19c36-280">SaveLocation.ONEDRIVE_FOR_BUSINESS</span><span class="sxs-lookup"><span data-stu-id="19c36-280">SaveLocation.ONEDRIVE_FOR_BUSINESS</span></span>
* <span data-ttu-id="19c36-281">SaveLocation.LOCAL</span><span class="sxs-lookup"><span data-stu-id="19c36-281">SaveLocation.LOCAL</span></span>
* <span data-ttu-id="19c36-282">SaveLocation.SHAREPOINT</span><span class="sxs-lookup"><span data-stu-id="19c36-282">SaveLocation.SHAREPOINT</span></span>

在此之前,能用來判斷使用者的原則是否允許他們將資料儲存至各種位置的方法,為位於相同 AppPolicy 類別中的 getIsSaveToPersonalAllowed()The previous method of determining whether a user’s policy allowed them to save data to various locations was getIsSaveToPersonalAllowed() within the same AppPolicy class. 此函數目前已「被取代」,且不應該使用。下列的引動過程等同於 getIsSaveToPersonalAllowed()This function is now deprecated and should not be used, the following invocation is equivalent to getIsSaveToPersonalAllowed():


MAMPolicyManager.getPolicy(currentActivity).getIsSaveToLocationAllowed(SaveLocation.LOCAL, userNameInQuestion);

注意

若目標位置沒有列於 SaveLocations 列舉中,請使用 SaveLocation.OTHERUse SaveLocation.OTHER if the location in question is not listed in the SaveLocations enum.

從 SDK 註冊通知Register for notifications from the SDK

概觀Overview

當 IT 系統管理員部署特定原則時 (例如選擇性抹除),Intune App SDK 可讓您的應用程式控制其行為。The Intune App SDK allows your app to control the behavior of certain policies, such as selective wipe, when they are deployed by the IT administrator. 當 IT 系統管理員部署這類原則時,Intune 服務會傳送通知給 SDK。When an IT administrator deploys such a policy, the Intune service sends down a notification to the SDK.

您的應用程式必須建立 MAMNotificationReceiver,並向 MAMNotificationReceiverRegistry 註冊它,才能從 SDK 註冊通知。Your app must register for notifications from the SDK by creating a MAMNotificationReceiver and registering it with MAMNotificationReceiverRegistry. 這是藉由提供接收者以及想要在 App.onCreate 中接收的通知類型來完成,如下列範例所示:This is done by providing the receiver and the type of notification desired in App.onCreate, as the example below illustrates:

@Override
public void onCreate() {
    super.onCreate();
    MAMComponents.get(MAMNotificationReceiverRegistry.class)
        .registerReceiver(
            new ToastNotificationReceiver(),
            MAMNotificationType.WIPE_USER_DATA);
    }

MAMNotificationReceiverMAMNotificationReceiver

MAMNotificationReceiver 介面只會從 Intune 服務接收通知。The MAMNotificationReceiver interface simply receives notifications from the Intune service. 有些通知是由 SDK 直接處理,有些則需要應用程式的參與。Some notifications are handled by the SDK directly, while others require the app's participation. 應用程式必須針對通知傳回 true 或 false。An app must return either true or false from a notification. 除非基於通知結果,應用程式嘗試採取的某些動作失敗,否則一律會傳回 true。It must always return true unless some action it tried to take as a result of the notification failed.

  • 這類失敗可能會回報給 Intune 服務。This failure may be reported to the Intune service. 例如,如果在 IT 系統管理員起始抹除之後,應用程式無法抹除使用者資料,就會進行回報。An example of a scenario to report is if the app fails to wipe user data after the IT administrator initiates a wipe.

注意

您可以放心封鎖 MAMNotificationReceiver.onReceive,因為其回呼不會在 UI 執行緒上執行。It is safe to block in MAMNotificationReceiver.onReceive because its callback is not running on the UI thread.

於 SDK 中定義的 MAMNotificationReceiver 介面已包含於下列內容中:The MAMNotificationReceiver interface as defined in the SDK is included below :

/**
 * The SDK is signaling that a MAM event has occurred.
 *
 */
public interface MAMNotificationReceiver {

    /**
     * A notification was received.
     *
     * @param notification
     *            The notification that was received.
     * @return The receiver should return true if it handled the
     *   notification without error (or if it decided to ignore the
     *   notification). If the receiver tried to take some action in
     *   response to the notification but failed to complete that
     *   action it should return false.
     */
    boolean onReceive(MAMNotification notification);
}

通知類型Types of notifications

下列通知會傳送至應用程式,且其中部分通知可能需要應用程式參與:The following notifications are sent to the app and some of them may require app participation:

  • WIPE_USER_DATA︰這個通知是在 MAMUserNotification 類別中傳送。WIPE_USER_DATA: This notification is sent in a MAMUserNotification class. 收到這項通知時,應用程式應該刪除與 MAMUserNotification 一起傳遞之「公司」身分識別相關聯的所有資料。When this notification is received, the app is expected to delete all data associated with the "corporate" identity passed with the MAMUserNotification. 這項通知目前會在 APP-WE 服務取消註冊期間傳送。This notification is currently sent during APP-WE service unenrollment. 使用者主要名稱通常會在註冊程序期間指定。The user's primary name is typically specified during the enrollment process. 如果您註冊這項通知,您的應用程式必須確定所有使用者資料都已刪除。If you register for this notification, your app must ensure that all the user's data has been deleted. 如果您未註冊,就會執行預設的選擇性抹除行為。If you don't register for it, the default selective wipe behavior will be performed.

  • WIPE_USER_AUXILIARY_DATA:如果應用程式要 Intune App SDK 執行預設選擇性抹除行為,但仍想要在抹除發生時移除部分輔助資料,則可註冊這項通知。WIPE_USER_AUXILIARY_DATA: Apps can register for this notification if they'd like the Intune App SDK to perform the default selective wipe behavior, but would still like to remove some auxiliary data when the wipe occurs.

  • REFRESH_POLICY︰這項通知是在 MAMUserNotification 中傳送。REFRESH_POLICY: This notification is sent in a MAMUserNotification. 收到這項通知時,所有快取的 Intune 原則都必須處於失效狀態並加以更新。When this notification is received, any cached Intune policy must be invalidated and updated. 通常,SDK 會處理這項作業,不過如果原則是以任何持續性的方式使用,則應該由應用程式來處理。This is generally handled by the SDK; however, it should be handled by the app if the policy is used in any persistent way.

  • MANAGEMENT_REMOVED:這項通知是在 MAMUserNotification 中傳送,並會通知應用程式它即將成為未受管理。MANAGEMENT_REMOVED: This notification is sent in a MAMUserNotification and informs the app that it is about to become unmanaged. 應用程式成為未受管理之後,它將無法讀取加密的檔案、讀取以 MAMDataProtectionManager 加密的檔案、與加密的剪貼簿互動,或參與受管理應用程式的生態系統。Once unmanaged, it will no longer be able to read encrypted files, read data encrypted with MAMDataProtectionManager, interact with the encrypted clipboard, or otherwise participate in the managed-app ecosystem.

注意

應用程式永遠不得同時註冊 WIPE_USER_DATAWIPE_USER_AUXILIARY_DATA 通知。An app should never register for both the WIPE_USER_DATA and WIPE_USER_AUXILIARY_DATA notifications.

設定 Azure Active Directory Authentication Library (ADAL)Configure Azure Active Directory Authentication Library (ADAL)

首先,請參閱 GitHub 上 ADAL 存放庫 (英文) 中的 ADAL 整合方針。First, please read the ADAL integration guidelines found in the ADAL repository on GitHub.

SDK 仰賴 ADAL 進行驗證和條件式啟動案例,其中需要應用程式針對 Azure Active Directory進行設定。The SDK relies on ADAL for its authentication and conditional launch scenarios, which require apps to be configured with Azure Active Directory. 設定值會透過 AndroidManifest 中繼資料傳送給 SDK。The configuration values are communicated to the SDK via AndroidManifest metadata.

若要設定您的應用程式並啟用適當的驗證,請將下列項目加入 AndroidManifest.xml 中的應用程式節點。To configure your app and enable proper authentication, add the following to the app node in AndroidManifest.xml. 一般來說,其中某些設定僅在您的應用程式會使用 ADAL 來進行驗證時才需要;在此情況下,您必須具備應用程式使用的特定值,以向 AAD 註冊該應用程式。Some of these configurations are only required if your app uses ADAL for authentication in general; in that case, you will need the specific values your app uses to register itself with AAD. 這是為了確保使用者不會因為 AAD 辨識兩個不同的登錄值 (一個來自應用程式,另一個則來自 SDK),而收到兩次驗證提示。This is done to ensure that the end user does not get prompted for authentication twice, due to AAD recognizing two separate registration values: one from the app and one from the SDK.

<meta-data
    android:name="com.microsoft.intune.mam.aad.Authority"
    android:value="https://AAD authority/" />
<meta-data
    android:name="com.microsoft.intune.mam.aad.ClientID"
    android:value="your-client-ID-GUID" />
<meta-data
    android:name="com.microsoft.intune.mam.aad.NonBrokerRedirectURI"
    android:value="your-redirect-URI" />
<meta-data
    android:name="com.microsoft.intune.mam.aad.SkipBroker"
    android:value="[true | false]" />

ADAL 中繼資料ADAL metadata

  • Authority 為目前使用的 AAD 授權單位。Authority is the current AAD authority in use. 若存在,您應該使用自己的環境 (其中已設定 AAD 帳戶)。If present, you should use your own environment where AAD accounts have been configured. 如果此值不存在,則會使用 Intune 預設值。If this value is absent, an Intune default is used.

  • ClientID 為要使用的 AAD ClientID。ClientID is the AAD ClientID to be used. 如果應用程式的 ClientID 已經向 Azure AD 註冊,您應該使用此 ClientID。You should use your own app's ClientID if it is registered with Azure AD. 如果此值不存在,則會使用 Intune 預設值。If this value is absent, an Intune default is used.

  • NonBrokerRedirectURI 為要在無 Broker 的情況下使用的 AAD 重新導向 URI。NonBrokerRedirectURI is the AAD redirect URI to use in broker-less cases. 如果未指定,就會使用預設值 urn:ietf:wg:oauth:2.0:oobIf none is specified, a default value of urn:ietf:wg:oauth:2.0:oob is used. 此預設值適用於大部分的應用程式。This default is suitable for most apps.

  • SkipBroker 會在 ClientID 未設定為使用 Broker 重新導向 URI 的情況下使用。SkipBroker is used in case the ClientID has not been configured to use the broker redirect URI. 預設值為 "false"。The default value is "false."

    • 針對「不會整合 ADAL」及「不想要參與全裝置代理驗證/SSO」的應用程式,此值應設為 "true"。For apps that do not integrate ADAL and do not want to participate in device-wide brokered authentication/SSO, this should be set to "true." 當此值為 "true" 時,唯一會使用的重新導向 URI 為 NonBrokerRedirectURI。When this value is "true," the only redirect URI that will be used is NonBrokerRedirectURI.

    • 針對支援全裝置 SSO 代理的應用程式,此值應為 "false"。For apps that do support device-wide SSO brokering, this should be "false." 當此值為 "false" 時,SDK 將會根據 Broker 在系統上的可用性,於 com.microsoft.aad.adal.AuthenticationContext.getRedirectUriForBroker() 和 NonBrokerRedirectURI 的結果之間選取 Broker。When the value is "false," the SDK will select a broker between the result of com.microsoft.aad.adal.AuthenticationContext.getRedirectUriForBroker() and NonBrokerRedirectURI, based on the availability of the broker on the system. 一般而言,Broker 將會從公司入口網站應用程式,或 Azure Authenticator 應用程式提供。In general, the broker will be available from the Company Portal app or Azure Authenticator app.

ADAL 的常見設定Common ADAL configurations

下列為應用程式可以搭配 ADAL 進行設定的常見方式。The following are common ways an app can be configured with ADAL. 尋找您應用程式的設定,並確保 ADAL 中繼資料參數 (如上所述) 已設定為必要的值。Find your app's configuration and make sure to set the ADAL metadata parameters (explained above) to the necessary values.

  1. 應用程式不會整合 ADAL:App does not integrate ADAL:

    必要的 ADAL 參數Required ADAL parameter Value
    AuthorityAuthority 已設定 AAD 帳戶的所需環境Desired environment where AAD accounts have been configured
    SkipBrokerSkipBroker TrueTrue
  2. 應用程式會整合 ADAL:App integrates ADAL:

    必要的 ADAL 參數Required ADAL parameter Value
    AuthorityAuthority 已設定 AAD 帳戶的所需環境Desired environment where AAD accounts have been configured
    ClientIDClientID 應用程式的 ClientID (由 Azure AD 於應用程式註冊時產生)The app's ClientID (generated by Azure AD when the app is registered)
    NonBrokerRedirectURINonBrokerRedirectURI 應用程式的有效重新導向 URI,或是 urn:ietf:wg:oauth:2.0:oobA valid redirect URI for the app, or urn:ietf:wg:oauth:2.0:oob

    .

    請務必將值設定為您應用程式 ClientID 可接受的重新導向 URI。Make sure to configure the value as an acceptable redirect URI for your app's ClientID. | SkipBroker | False || SkipBroker | False |

  3. 應用程式會整合 ADAL,但不支援代理驗證/全裝置 SSO:App integrates ADAL but does not support brokered authentication/device-wide SSO:

    必要的 ADAL 參數Required ADAL parameter Value
    AuthorityAuthority 已設定 AAD 帳戶的所需環境Desired environment where AAD accounts have been configured
    ClientIDClientID 應用程式的 ClientID (由 Azure AD 於應用程式註冊時產生)The app's ClientID (generated by Azure AD when the app is registered)
    NonBrokerRedirectURINonBrokerRedirectURI 應用程式的有效重新導向 URI,或是預設值 urn:ietf:wg:oauth:2.0:oobA valid redirect URI for the app, or urn:ietf:wg:oauth:2.0:oob by default.

    請務必將值設定為您應用程式 ClientID 可接受的重新導向 URI。Make sure to configure the value as an acceptable redirect URI for your app's ClientID.
    SkipBrokerSkipBroker TrueTrue

無裝置註冊的應用程式保護原則App protection policy without device enrollment

概觀Overview

無裝置註冊的 Intune 應用程式保護原則 (也稱為 APP-WE 或 MAM-WE) 可讓 Intune 管理應用程式,而不需要向 Intune MDM 註冊裝置。Intune app protection policy without device enrollment, also known as APP-WE or MAM-WE, allows apps to be managed by Intune without the need for the device to be enrolled Intune MDM. APP-WE 無論是否搭配裝置註冊皆可以運作。APP-WE works with or without device enrollment. 公司入口網站仍然需要安裝於裝置上,但使用者並不需要登入公司入口網站並註冊該裝置。The Company Portal is still required to be installed on the device, but the user does not need to sign into the Company Portal and enroll the device.

注意

所有應用程式都必須支援無裝置註冊的應用程式保護原則。All apps are required to support app protection policy without device enrollment.

工作流程Workflow

當應用程式建立新使用者帳戶時,它應該註冊該帳戶以使用 Intune App SDK 進行管理。When an app creates a new user account, it should register the account for management with the Intune App SDK. SDK 會處理在 APP-WE 服務中註冊應用程式的細節。若有需要,它會在發生失敗的情況下,以適當的時間間隔重試任何註冊。The SDK will handle the details of enrolling the app in the APP-WE service; if necessary, it will retry any enrollments at appropriate time intervals if failures occur.

應用程式也可以向 Intune App SDK 查詢已註冊的使用者,以判斷是否應封鎖該使用者存取公司內容。The app can also query the Intune App SDK for the status of a registered user to determine if the user should be blocked from accessing corporate content. 您可以註冊多個帳戶以進行管理,但目前一次只能針對 APP-WE 服務註冊一個帳戶。Multiple accounts may be registered for management, but currently only one account can be actively enrolled with the APP-WE service at a time. 這代表應用程式上一次只有一個帳戶可以接收應用程式保護原則。This means only one account on the app can receive app protection policy at a time.

該應用程式必須提供回呼,以代表 SDK 從 Azure Active Directory Authentication Library (ADAL) 取得適當的存取權杖。The app is required to provide a callback to acquire the appropriate access token from the Azure Active Directory Authentication Library (ADAL) on behalf of the SDK. 它會假設該應用程式已經使用 ADAL 以進行使用者驗證,以及用來取得自己的存取權杖。It is assumed that the app already uses ADAL for user authentication and to acquire its own access tokens.

當應用程式完全移除某個帳戶時,它應該會取消該帳戶的註冊,以指出應用程式已不再針對該使用者套用原則。When the app removes an account completely, it should unregister that account to indicate that the app should no longer apply policy for that user. 如果該使用者曾註冊 MAM 服務,系統會將他取消註冊並抹除應用程式。If the user was enrolled in the MAM service, the user will be unenrolled and the app will be wiped.

應用程式需求概觀Overview of app requirements

若要實作 APP-WE 整合,您的應用程式必須向 MAM SDK 註冊使用者帳戶:To implement APP-WE integration, your app must register the user account with the MAM SDK:

  1. 應用程式「必須」實作並註冊 MAMServiceAuthenticationCallback 介面的執行個體。The app must implement and register an instance of the MAMServiceAuthenticationCallback interface. 回呼執行個體必須盡早於應用程式的生命週期內進行註冊 (通常是在應用程式類別的 onMAMCreate() 方法中)。The callback instance should be registered as early as possible in the app's lifecycle (typically in the onMAMCreate() method of the application class).

  2. 在建立使用者帳戶,且使用者成功以 ADAL 登入之後,應用程式「必須」呼叫 registerAccountForMAM()When a user account is created and the user successfully signs in with ADAL, the app must call the registerAccountForMAM().

  3. 當使用者帳戶已完全移除之後,應用程式應該呼叫 unregisterAccountForMAM() 以將帳戶從 Intune 管理中移除。When a user account is completely removed, the app should call unregisterAccountForMAM() to remove the account from Intune management.

    注意

    如果使用者暫時登出應用程式,應用程式並不需要呼叫 unregisterAccountForMAM()If a user signs out of the app temporarily, the app does not need to call unregisterAccountForMAM(). 呼叫可以初始化抹除,以完全移除該使用者的公司資料。The call may initiate a wipe to completely remove corporate data for the user.

MAMEnrollmentManagerMAMEnrollmentManager

所有必要的驗證和註冊 API 都可以在 MAMEnrollmentManager 介面中找到。All the necessary authentication and registration APIs can be found in the MAMEnrollmentManager interface. 針對 MAMEnrollmentManager 的參考可以透過下列方式取得:A reference to the MAMEnrollmentManager can be obtained as follows:

MAMEnrollmentManager mgr = MAMComponents.get(MAMEnrollmentManager.class);

// make use of mgr

傳回的 MAMEnrollmentManager 執行個體將保證不會為 null。The MAMEnrollmentManager instance returned is guaranteed not to be null. API 方法會落入兩個類別:「驗證」和「帳戶註冊」。The API methods fall into two categories: authentication and account registration.

注意

MAMEnrollmentManager 包含一些即將被取代的 API 方法。MAMEnrollmentManager contains some API methods that will be deprecated soon. 為了清楚呈現,下列程式碼區塊只會顯示相關的方法和結果程式碼。For clarity, only the relevant methods and result codes are shown in the code block below.

package com.microsoft.intune.mam.policy;

public interface MAMEnrollmentManager {
    public enum Result {
        AUTHORIZATION_NEEDED,
        NOT_LICENSED,
        ENROLLMENT_SUCCEEDED,
        ENROLLMENT_FAILED,
        WRONG_USER,
        MDM_ENROLLED,
        UNENROLLMENT_SUCCEEDED,
        UNENROLLMENT_FAILED,
        PENDING,
        COMPANY_PORTAL_REQUIRED;
    }

    //Authentication methods
    interface MAMServiceAuthenticationCallback {
        String acquireToken(String upn, String aadId, String resourceId);
    }
    void registerAuthenticationCallback(MAMServiceAuthenticationCallback callback);
    void updateToken(String upn, String aadId, String resourceId, String token);

    //Registration methods
    void registerAccountForMAM(String upn, String aadId, String tenantId);
    void unregisterAccountForMAM(String upn);
    Result getRegisteredAccountStatus(String upn);
}

帳戶驗證Account authentication

本節會描述 MAMEnrollmentManager 中的驗證 API 方法,以及使用它們的方式。This section describes the authentication API methods in MAMEnrollmentManager and how to use them.

interface MAMServiceAuthenticationCallback {
        String acquireToken(String upn, String aadId, String resourceId);
}
void registerAuthenticationCallback(MAMServiceAuthenticationCallback callback);
void updateToken(String upn, String aadId, String resourceId, String token);
  1. 應用程式必須實作 MAMServiceAuthenticationCallback 介面,以允許 SDK 針對指定使用者和資源識別碼要求 ADAL 權杖。The app must implement the MAMServiceAuthenticationCallback interface to allow the SDK to request an ADAL token for the given user and resource ID. 回呼執行個體必須提供給 MAMEnrollmentManager,方法是呼叫其 registerAuthenticationCallback() 方法。The callback instance must be provided to the MAMEnrollmentManager by calling its registerAuthenticationCallback() method. 在應用程式生命週期相當早的階段,可能會需要權杖以進行註冊重試或應用程式保護原則重新整理簽入,因此註冊回呼的理想位置是在應用程式 MAMApplication 子類別的 onMAMCreate() 方法中。A token may be needed very early in the app lifecycle for enrollment retries or app protection policy refresh check-ins, so the ideal place to register the callback is in the onMAMCreate() method of the app's MAMApplication subclass.

  2. acquireToken() 方法應該會取得針對指定使用者所要求之資源識別碼的存取權杖。The acquireToken() method should acquire the access token for the requested resource ID for the given user. 如果它無法取得要求的權杖,便應該會傳回 null。If it can't acquire the requested token, it should return null.

  3. 在應用程式無法於 SDK 呼叫 acquireToken() 時提供權杖的情況下 (例如,如果無訊息驗證失敗,且當時並不方便顯示 UI),該應用程式可以透過呼叫 updateToken() 方法來在稍後提供權杖。In case the app is unable to provide a token when the SDK calls acquireToken() -- for example, if silent authentication fails and it is an inconvenient time to show a UI -- the app can provide a token at a later time by calling the updateToken() method. 由先前針對 acquireToken() 的呼叫所要求的 UPN、AAD 識別碼及資源識別碼,必須連同最終取得的權杖一起傳遞至 updateToken()The same UPN, AAD ID, and resource ID that were requested by the prior call to acquireToken() must be passed to updateToken(), along with the token that was finally acquired. 應用程式應該在從所提供的回呼傳回 null 之後盡快呼叫此方法。The app should call this method as soon as possible after returning null from the provided callback.

注意

SDK 將會定期呼叫 acquireToken() 以取得權杖,因此並不一定需要呼叫 updateToken()The SDK will call acquireToken() periodically to get the token, so calling updateToken() is not strictly required. 不過,我們建議您這麼做,因為這可以協助註冊和應用程式保護原則簽入及時完成。However, it is recommended as it can help enrollments and app protection policy check-ins complete in a timely manner.

帳戶註冊Account registration

本節會描述 MAMEnrollmentManager 中的帳戶註冊 API 方法,以及使用它們的方式。This section describes the account registration API methods in MAMEnrollmentManager and how to use them.

void registerAccountForMAM(String upn, String aadId, String tenantId);
void unregisterAccountForMAM(String upn);
Result getRegisteredAccountStatus(String upn);
  1. 若要註冊帳戶以進行管理,應用程式應呼叫 registerAccountForMAM()To register an account for management, the app should call registerAccountForMAM(). 識別使用者帳戶的方式,是透過其 UPN 和 AAD 使用者識別碼。A user account is identified by both its UPN and its AAD user ID. 同時也需要租用戶識別碼,以關聯註冊資料與使用者的 AAD 租用戶。The tenant ID is also required to associate enrollment data with the user's AAD tenant. SDK 可能會嘗試在 MAM 服務中針對指定使用者註冊應用程式。若註冊失敗,它將會定期重試註冊,直到該帳戶已取消註冊為止。The SDK may attempt to enroll the app for the given user in the MAM service; if enrollment fails, it will periodically retry enrollment until the account is unregistered. 重試的間隔通常是 12-24 小時。The retry period will typically be 12-24 hours. SDK 會透過通知以非同步的方式提供註冊嘗試的狀態。The SDK provides the status of enrollment attempts asynchronously via notifications.

  2. 由於需要 AAD 驗證,註冊使用者帳戶的最佳時間是在使用者登入應用程式,並成功使用 ADAL 進行驗證之後。Because AAD authentication is required, the best time to register the user account is after the user has signed into the app and is successfully authenticated using ADAL.

    • 做為 AuthenticationResult 物件的一部分,使用者的 AAD 識別碼和租用戶識別碼會從 ADAL 驗證呼叫傳回。The user's AAD ID and tenant ID are returned from the ADAL authentication call as part of the AuthenticationResult object. 租用戶識別碼是來自 AuthenticationResult.getTenantID() 方法。The tenant ID comes from the AuthenticationResult.getTenantID() method.
    • 有關使用者的資訊是位於來自 AuthenticationResult.getUserInfo()UserInfo 類型的子物件中,而 AAD 使用者識別碼則是透過呼叫 UserInfo.getUserId() 以從該物件中擷取。Information about the user is found in a sub-object of type UserInfo that comes from AuthenticationResult.getUserInfo(), and the AAD user ID is retrieved from that object by calling UserInfo.getUserId().
  3. 若要從 Intune 管理取消註冊某個帳戶,應用程式應呼叫 unregisterAccountForMAM()To unregister an account from Intune management, the app should call unregisterAccountForMAM(). 若該帳戶已成功註冊並受到管理,SDK 將會取消註冊該帳戶並抹除其資料。If the account has been successfully enrolled and is managed, the SDK will unenroll the account and wipe its data. 該帳戶的定期註冊重試將會停止。Periodic enrollment retries for the account will be stopped. SDK 會透過通知以非同步的方式提供取消註冊要求的狀態。The SDK provides the status of unenrollment request asynchronously via notifications.

重要實作附註Important implementation notes

驗證Authentication

  • 當應用程式呼叫 registerAccountForMAM() 時,它可能會在不久之後於其 MAMServiceAuthenticationCallback 介面上接收到不同執行緒的回呼。When the app calls registerAccountForMAM(), it may receive a callback on its MAMServiceAuthenticationCallback interface shortly thereafter, on a different thread. 在理想的情況下,應用程式已在註冊帳戶之前從 ADAL 取得自己的權杖,以加快取得 MAMService 權杖的速度。Ideally, the app acquired its own token from ADAL prior to registering the account to expedite the acquisition of the MAMService token. 如果應用程式從回呼傳回有效權杖,則註冊將會繼續,且應用程式將會透過通知取得最終結果。IF the app returns a valid token from the callback, enrollment will proceed and the app will get the final result via a notification.

  • 如果應用程式沒有傳回有效的 AAD 權杖,來自註冊嘗試的最終結果將會是 AUTHENTICATION_NEEDEDIf the app doesn't return a valid AAD token, the final result from the enrollment attempt will be AUTHENTICATION_NEEDED. 如果應用程式透過通知接收到此結果,它可以透過取得 MAMService 權杖,並呼叫 updateToken() 方法以再次初始化註冊程序,來加快註冊程序的速度。If the app receives this Result via notification, it can expedite the enrollment process by acquiring the MAMService token and calling the updateToken() method to initiate the enrollment process again. 這並「不是」強制的需求,不過由於 SDK 會定期重試註冊並叫用回呼以取得權杖,This is not a firm requirement, however, since the SDK retries enrollment periodically and invokes the callback to acquire the token.

  • 因此也會呼叫應用程式的已註冊 MAMServiceAuthenticationCallback,以取得定期應用程式保護原則重新整理簽入的權杖。如果應用程式無法在要求時提供權杖,便不會收到通知,不過它應該於下一個適當的時機嘗試取得權杖並呼叫 updateToken(),以加速簽入程序。The app's registered MAMServiceAuthenticationCallback will also be called to acquire a token for periodic app protection policy refresh check-ins. If the app is unable to provide a token when requested, it will not get a notification, but it should attempt to acquire a token and call updateToken() at the next convenient time to expedite the check-in process. 如果不提供權杖,在下一個簽入嘗試時仍然會呼叫回呼。If a token is not provided, the callback will still be called at the next check-in attempt.

註冊Registration

  • 為了方便起見,註冊方法將會是等冪,例如 registerAccountForMAM() 只會在帳戶尚未註冊的情況下註冊該帳戶並嘗試註冊應用程式,而 unregisterAccountForMAM() 只會在帳戶已註冊的情況下將帳戶取消註冊。For your convenience, the registration methods are idempotent; for example, registerAccountForMAM()will only register an account and attempt to enroll the app if the account is not already registered, and unregisterAccountForMAM() will only unregister an account if it is currently registered. 後續的呼叫將不會運作,因此多次呼叫這些方法並不會有壞處。Subsequent calls are no-ops, so there is no harm in calling these methods more than once. 此外,針對這些方法的呼叫及結果通知之間的對應並不是保證的,也就是說,若針對已註冊的身分識別呼叫 registerAccountForMAM,便可能不會針對該身分識別再次傳送通知。Additionally, correspondence between calls to these methods and notifications of results are not guaranteed: i.e. if registerAccountForMAM is called for an identity that is already registered, the notification may not be sent again for that identity. 已傳送的通知有可能不會與針對這些方法的任何呼叫對應,因為 SDK 可能會定期嘗試在背景進行註冊,且從 Intune 服務接收的抹除要求可能會觸發取消註冊。It is possible that notifications are sent that don't correspond to any calls to these methods, since the SDK may periodically try enrollments in the background, and unenrollments may be triggered by wipe requests received from the Intune service.

  • 註冊方法可以針對任何數目的個別身分識別進行呼叫,但目前只能有一個使用者帳戶可以成功註冊。The registration methods can be called for any number of different identities, but currently only one user account can become successfully enrolled. 若有多個已針對 Intune 取得授權,並為應用程式保護原則之目標的使用者帳戶,在相同或相近的時間進行註冊,將無法保證哪一個帳戶會註冊成功。If multiple user accounts that are licensed for Intune and targeted by app protection policy are registered at or near the same time, there is no guarantee on which one will win the race.

  • 最後,您可以查詢 MAMEnrollmentManager 以使用 getRegisteredAccountStatus 方法來查看特定帳戶是否已註冊,以及取得其目前的狀態。Finally, you can query the MAMEnrollmentManager to see if a particular account is registered and to get its current status using the getRegisteredAccountStatus method. 若所提供的帳戶尚未註冊,此方法將會傳回 nullIf the provided account is not registered, this method will return null. 若帳戶已註冊,此方法將會以 MAMEnrollmentManager.Result 列舉之其中一個成員的方式傳回該帳戶的狀態。If the account is registered, this method will return the account's status as one of the members of the MAMEnrollmentManager.Result enumeration.

結果和狀態碼Result and status codes

當帳戶註冊時,它一開始會處於 PENDING 狀態,表示初始 MAM 服務註冊嘗試尚未完成。When an account is first registered, it begins in the PENDING state, indicating that the initial MAM service enrollment attempt is incomplete. 在註冊嘗試完成之後,將會傳送具有下表其中一個結果碼的通知。After the enrollment attempt finishes, a notification will be sent with one of the Result codes in the table below. 此外,getRegisteredAccountStatus() 方法將會傳回帳戶的狀態,使應用程式可以持續判斷該使用者對公司內容的存取是否已被封鎖。In addition, the getRegisteredAccountStatus() method will return the account's status so the app can always determine if access to corporate content is blocked for that user. 若註冊嘗試失敗,帳戶的狀態可能會隨著 SDK 於背景重試註冊而變更。If the enrollment attempt fails, the account's status may change over time as the SDK retries enrollment in the background.

結果碼Result code 說明Explanation
AUTHORIZATION_NEEDEDAUTHORIZATION_NEEDED 此結果表示應用程式的已註冊 MAMServiceAuthenticationCallback 執行個體沒有提供權杖,或是提供的權杖無效。This result indicates that a token was not provided by the app’s registered MAMServiceAuthenticationCallback instance, or the provided token was invalid. 若可能的話,應用程式應該取得有效的權杖並呼叫 updateToken()The app should acquire a valid token and call updateToken() if possible.
NOT_LICENSEDNOT_LICENSED 使用者沒有針對 Intune 取得授權,或是連絡 Intune MAM 服務的嘗試失敗。The user is not licensed for Intune, or the attempt to contact the Intune MAM service failed. 應用程式應該會持續以未受管理 (一般) 的狀態進行,且使用者應該不會被封鎖。The app should continue in an unmanaged (normal) state and the user should not be blocked. 註冊將會定期進行重試,以防使用者於日後取得授權。Enrollments will be retried periodically in case the user becomes licensed in the future.
ENROLLMENT_SUCCEEDEDENROLLMENT_SUCCEEDED 註冊嘗試成功,或是使用者已經註冊。The enrollment attempt succeeded, or the user is already enrolled. 針對成功註冊的情況,將會在此通知之前傳送原則重新整理的通知。In the case of a successful enrollment, a policy refresh notification will be sent before this notification. 應用程式應該會允許針對公司資料的存取。Access to corporate data should be allowed.
ENROLLMENT_FAILEDENROLLMENT_FAILED 註冊嘗試失敗。The enrollment attempt failed. 您可以在裝置記錄檔中找到進一步的詳細資料。Further details can be found in the device logs. 在此狀態下,應用程式應該不會允許對公司資料的存取,因為先前已判斷使用者已針對 Intune 取得授權。The app should not allow access to corporate in this state, since it was previously determined that the user is licensed for Intune.
WRONG_USERWRONG_USER 每個裝置上只能有一個使用者可以將應用程式與 MAM 服務進行註冊。Only one user per device can enroll an app with the MAM service. 若要以不同使用者的身分成功進行註冊,所有已註冊的應用程式都必須先取消註冊。In order to enroll successfully as a different user, all enrolled apps must be unenrolled first. 否則,此應用程式必須以主要使用者的身分進行註冊。Otherwise, this app must enroll as the primary user. 此檢查會在授權檢查之後發生,因此在該應用程式成功註冊之前,使用者將無法存取公司資料。This check happens after the license check, so the user should be blocked from accessing corporate data until the app is successfully enrolled.
UNENROLLMENT_SUCCEEDEDUNENROLLMENT_SUCCEEDED 已順利完成取消註冊。Unenrollment was successful.
UNENROLLMENT_FAILEDUNENROLLMENT_FAILED 取消註冊要求失敗。The unenrollment request failed. 您可以在裝置記錄檔中找到進一步的詳細資料。Further details can be found in the device logs.
PENDINGPENDING 使用者的初始註冊嘗試正在進行中。The initial enrollment attempt for the user is in progress. 應用程式可以 (但非必要) 封鎖對公司資料的存取,直到知道註冊狀態為止。The app can block access to corporate data until the enrollment result is known, but is not required to do so.
COMPANY_PORTAL_REQUIREDCOMPANY_PORTAL_REQUIRED 使用者已針對 Intune 取得授權,但在裝置上安裝公司入口網站應用程式之前,將無法註冊應用程式。The user is licensed for Intune, but the app cannot be enrolled until the Company Portal app is installed on the device. Intune App SDK 會嘗試封鎖特定使用者對應用程式的存取,並引導他們安裝公司入口網站應用程式 (請參閱下方以取得詳細資料)。The Intune App SDK will attempt to block access to the app for the given user and direct them to install the Company Portal app (see below for details).

公司入口網站需求提示覆寫 (選擇性)Company Portal requirement prompt override (optional)

如果接收到 COMPANY_PORTAL_REQUIRED 結果,SDK 將會封鎖使用要求註冊之身分識別的活動。If the COMPANY_PORTAL_REQUIRED Result is received, the SDK will block use of activities that use the identity for which enrollment was requested. 相反地,SDK 將會使那些活動顯示下載公司入口網站的提示。Instead, the SDK will cause those activities to display a prompt to download the Company Portal. 如果您想要在應用程式中避免此行為,可以讓活動實作 MAMActivity.onMAMCompanyPortalRequiredIf you want to prevent this behavior in your app, activities may implement MAMActivity.onMAMCompanyPortalRequired.

此方法會在 SDK 顯示其預設封鎖 UI 之前呼叫。This method is called before the SDK displays its default blocking UI. 如果應用程式變更活動身分識別,或是將嘗試註冊的使用者取消註冊,SDK 將不會封鎖該活動。If the app changes the activity identity or unregisters the user who attempted to enroll, the SDK will not block the activity. 在此情況下,應用程式必須負責避免洩漏公司資料。In this situation, it is up to the app to avoid leaking corporate data.

通知Notifications

已新增 MAMNotification 的新類型,以通知應用程式註冊要求已完成。A new type of MAMNotification has been added in order to inform the app that the enrollment request has completed. 將會透過 MAMNotificationReceiver 介面接收 MAMEnrollmentNotification,如從 SDK 註冊通知一節中所述。The MAMEnrollmentNotification will be received through the MAMNotificationReceiver interface as described in the Register for notifications from the SDK section.

public interface MAMEnrollmentNotification extends MAMUserNotification {
    MAMEnrollmentManager.Result getEnrollmentResult();
}

getEnrollmentResult() 方法會傳回註冊要求的結果。The getEnrollmentResult() method returns the result of the enrollment request. 由於 MAMEnrollmentNotification 會延伸 MAMUserNotification,因此也會提供嘗試註冊的使用者身分識別。Since MAMEnrollmentNotification extends MAMUserNotification, the identity of the user for whom the enrollment was attempted is also available. 應用程式必須實作 MAMNotificationReceiver 介面以接收這些通知,這已在從 SDK 註冊通知一節中詳述。The app must implement the MAMNotificationReceiver interface to receive these notifications, detailed in the Register for notifications from the SDK section.

已註冊使用者帳戶的狀態在接收註冊通知時可能會變更,但在某些情況下將不會變更,例如,若在接收較具資訊性的結果 (例如 WRONG_USER) 之後接收到 AUTHORIZATION_NEEDED 通知,則系統將會維持使用較具資訊性的結果做為帳戶的狀態The registered user account's status may change when an enrollment notification is received, but it will not change in some cases (e.g. if AUTHORIZATION_NEEDED notification is received after a more informative result such as WRONG_USER, the more informative result will be maintained as the account's status)

保護備份資料Protecting Backup data

截至 Android Marshmallow (API 23) 止,Android 提供兩種可讓應用程式備份資料的方法。As of Android Marshmallow (API 23), Android has two ways for an app to back up its data. 您可在應用程式中使用這些選項,但需要不同的步驟以確保正確實作 Intune 資料保護。Each option is available to your app and requires different steps to ensure that Intune data protection is correctly implemented. 您可以檢閱下表,以了解正確資料保護行為所需的相對應動作。You can review the table below on corresponding actions required for correct data protection behavior. 您可以在 Android API 指南中深入了解備份方法。You can read more about the backup methods in the Android API guide.

應用程式的自動備份Auto Backup for Apps

Android 開始針對 Android Marshmallow 裝置上的應用程式提供 Google 雲端硬碟的自動完整備份 (英文),不論應用程式的目標 API 為何。Android began offering automatic full backups to Google Drive for apps on Android Marshmallow devices, regardless of the app's target API. 在您的 AndroidManifest.xml 中,如果您將 android:allowBackup 明確設定為 false,則 Android 永遠不會將您的應用程式排入佇列進行備份,而且「公司」資料會保留在應用程式內。In your AndroidManifest.xml, if you explicitly set android:allowBackup to false, then your app will never be queued for backups by Android and "corporate" data will stay within the app. 在這種情況下,並不需要採取任何進一步的動作。In this case, no further action is necessary.

不過,android:allowBackup 屬性預設會設定為 true,即使未在資訊清單檔中指定 android:allowBackup 亦然。However, by default the android:allowBackup attribute is set to true, even if android:allowBackup isn't specified in the manifest file. 這表示所有應用程式資料都會自動備份至使用者的 Google 雲端硬碟帳戶,此預設行為會造成資料洩漏的風險This means all app data is automatically backed up to the user's Google Drive account, a default behavior that poses a data leak risk. 因此,SDK 需進行下列所述的變更,以確保套用資料保護。Therefore, the SDK requires the changes outlined below to ensure that data protection is applied. 如果您想要讓應用程式在 Android Marshmallow 裝置上執行,請務必遵循下列方針,以妥善保護客戶資料。It is important to follow the guidelines below to protect customer data properly if you want your app to run on Android Marshmallow devices.

Intune 可讓您利用 Android 中可用的所有自動備份功能,包括在 XML 中定義自訂規則的功能,但您必須遵循下列步驟來保護資料:Intune allows you to utilize all the Auto Backup features available from Android, including the ability to define custom rules in XML, but you must follow the steps below to secure your data:

  1. 如果您的應用程式「不會」使用自己的自訂 BackupAgent,請使用預設 MAMBackupAgent 以允許進行符合 Intune 原則的自動完整備份。If your app does not use its own custom BackupAgent, use the default MAMBackupAgent to allow for automatic full backups that are Intune policy compliant. 如果您這麼做,則可以忽略 android:fullBackupOnly 資訊清單屬性,因為它並不適用於我們的備份代理程式。If you do this, you can ignore the android:fullBackupOnly manifest attribute, as it’s not applicable for our backup agent. 請將下列內容置於應用程式資訊清單中:Place the following in the app manifest:

    android:backupAgent="com.microsoft.intune.mam.client.app.backup.MAMDefaultBackupAgent"
    
  2. [選擇性] 如果您實作選擇性的自訂 BackupAgent,則必須使用 MAMBackupAgent 或 MAMBackupAgentHelper。[Optional] If you implemented an optional custom BackupAgent, you need to make sure to use MAMBackupAgent or MAMBackupAgentHelper. 請參閱下列各節。See the following sections. 請考慮改用 Intune 的 MAMDefaultFullBackupAgent (已於步驟 1 中詳述),它能針對 Android M 及更新版本提供簡易的備份功能。Consider switching to using Intune's MAMDefaultFullBackupAgent (described in step 1) which provides easy back up on Android M and above.

  3. 當您決定應用程式應該接收的完整備份類型 (未篩選、已篩選或無) 時,您必須將將屬性 android:fullBackupContent 設定為 true、false,或您應用程式中的 XML 資源。When you decide which type of full backup your app should receive (unfiltered, filtered, or none) you'll need to set the attribute android:fullBackupContent to true, false, or an XML resource in your app.

  4. 接著,您「必須」_將放入 android:fullBackupContent 的任何內容,複製到資訊清單中名為 com.microsoft.intune.mam.FullBackupContent 的 Metadata 標記中。Then, you must_ copy whatever you put into android:fullBackupContent into a metadata tag named com.microsoft.intune.mam.FullBackupContent in the manifest.

    範例 1:如果您想要讓應用程式具有完整備份並不排除任何內容,請將 android:fullBackupContent 屬性和 com.microsoft.intune.mam.FullBackupContent Metadata 標記設定為 trueExample 1: If you want your app to have full backups without exclusions, set both the android:fullBackupContent attribute and com.microsoft.intune.mam.FullBackupContent metadata tag to true:

    android:fullBackupContent="true"
    ...
    <meta-data android:name="com.microsoft.intune.mam.FullBackupContent" android:value="true" />  
    

    範例 2:如果您想要讓應用程式使用自己的自訂 BackupAgent,並選擇退出完整且符合 Intune 原則的自動備份,則必須將屬性和 Metadata 標記設定為 falseExample 2: If you want your app to use its custom BackupAgent and opt out of full, Intune policy compliant, automatic backups, you must set the attribute and metadata tag to false:

    android:fullBackupContent="false"
    ...
    <meta-data android:name="com.microsoft.intune.mam.FullBackupContent" android:value="false" />  
    

    範例 3︰如果您想要讓應用程式根據定義於 XML 檔案中的自訂規則進行完整備份,請將屬性和 Metadata 標記設定為相同的 XML 資源:Example 3: If you want your app to have full backups according to your custom rules defined in an XML file, please set the attribute and metadata tag to the same XML resource:

    android:fullBackupContent="@xml/my_scheme"
    ...
    <meta-data android:name="com.microsoft.intune.mam.FullBackupContent" android:resource="@xml/my_scheme" />  
    

金鑰/值備份Key/Value Backup

索引鍵/值備份 (英文) 選項可供所有 API 8+ 使用,並會將應用程式資料上傳至 Android Backup Service (英文)The Key/Value Backup option is available to all APIs 8+ and uploads app data to the Android Backup Service. 您應用程式每個使用者的資料量會限制為 5MB。The amount of data per user of your app is limited to 5MB. 如果您使用 [索引鍵/值備份],則必須使用 BackupAgentHelperBackupAgentIf you use Key/Value Backup, you must use a BackupAgentHelper or a BackupAgent.

BackupAgentHelperBackupAgentHelper

從原生 Android 功能性和 Intune MAM 整合的角度來看,BackupAgentHelper 都比 BackupAgent 容易實作。BackupAgentHelper is easier to implement than BackupAgent both in terms of native Android functionality and Intune MAM integration. BackupAgentHelper 可讓開發人員分別向 FileBackupHelperSharedPreferencesBackupHelper 註冊整個檔案和共用的喜好設定,並在建立 BackupAgentHelper 時將其加入。BackupAgentHelper allows the developer to register entire files and shared preferences to a FileBackupHelper and SharedPreferencesBackupHelper (respectively) which are then added to the BackupAgentHelper upon creation. 請遵循下列步驟以搭配 Intune MAM 使用 BackupAgentHelper:Follow the steps below to use a BackupAgentHelper with Intune MAM:

  1. 若要利用 BackupAgentHelper 進行多重身分識別備份,請遵循擴充 BackupAgentHelper (英文) 的 Android 指南。To utilize multi-identity backup with a BackupAgentHelper, follow the Android guide to Extending BackupAgentHelper.

  2. 使您的類別擴充 BackupAgentHelper、FileBackupHelper 及 SharedPreferencesBackupHelper 的 MAM 對等項目。Have your class extend the MAM equivalent of BackupAgentHelper, FileBackupHelper, and SharedPreferencesBackupHelper.

Android 類別Android class MAM 對等項目MAM equivalent
BackupAgentHelperBackupAgentHelper MAMBackupAgentHelperMAMBackupAgentHelper
FileBackupHelperFileBackupHelper MAMFileBackupHelperMAMFileBackupHelper
SharedPreferencesBackupHelperSharedPreferencesBackupHelper MAMSharedPreferencesBackupHelperMAMSharedPreferencesBackupHelper

遵循這些指導方針以成功進行多重身分識別備份及還原。Following these guidelines will lead to a successful multi-identity backup and restore.

BackupAgentBackupAgent

BackupAgent 可讓您更明確了解備份了哪些資料。A BackupAgent allows you to be much more explicit about what data is backed up. 由於開發人員是主要負責實作的人,因此必須進行更多的步驟才能確保從 Intune 取得適當的資料保護效果。Because the developer is fairly responsible for the implementation, there are more steps required to ensure appropriate data protection from Intune. 由於大部分工作都落在開發人員 (也就是您) 身上,因此有略多的作業涉及 Intune 的整合。Since most of the work is pushed onto you, the developer, Intune integration is slightly more involved.

整合 MAM:Integrate MAM:

  1. 請仔細閱讀索引鍵/值備份 (英文) 的 Android 指南,特別是擴充 BackupAgent (英文),以確保您的 BackupAgent 實作能遵循 Android 指導方針。Please carefully read the Android guide for Key/Value Backup and specifically Extending BackupAgent to ensure your BackupAgent implementation follows Android guidelines.

  2. 使您的類別擴充 MAMBackupAgentHave your class extend MAMBackupAgent.

多重身分識別備份:Multi-identity Backup:

  1. 在開始備份之前,請確定您計畫備份的檔案或資料緩衝區已確實「由 IT 系統管理員允許在多重身分識別的案例下進行備份」。Before beginning your backup, check that the files or data buffers you plan to back up are indeed permitted by the IT administrator to be backed up in multi-identity scenarios. 我們在 MAMFileProtectionManagerMAMDataProtectionManager 中提供 isBackupAllowed 函式以供您進行判斷。We provide you with the isBackupAllowed function in MAMFileProtectionManager and MAMDataProtectionManager to determine this. 如果檔案或資料緩衝區不能備份,您就不應該繼續將它包含在備份中。If the file or data buffer is not allowed to be backed up, then you should not continue including it in your backup.

  2. 在備份期間,如果想要備份在步驟 1 中檢查過的檔案識別,就必須使用您打算從其中擷取資料的檔案來呼叫 backupMAMFileIdentity(BackupDataOutput data, File … files)At some point during your backup, if you want to back up the identities for the files you checked in step 1, you must call backupMAMFileIdentity(BackupDataOutput data, File … files) with the files from which you plan to extract data. 這會自動建立新的備份實體,並將其寫入 BackupDataOutputThis will automatically create new backup entities and write them to the BackupDataOutput for you. 在還原時會自動使用這些實體。These entities will be automatically consumed upon restore.

多重身分識別還原:Multi-identity Restore:

《資料備份》指南在擴充 BackupAgent (英文) 一節中詳述還原應用程式資料的一般演算法,並提供程式碼範例。The Data Backup guide specifies a general algorithm for restoring your application’s data and provides a code sample in the Extending BackupAgent section. 若要成功進行多重身分識別還原,您必須遵循此程式碼範例中所提供的一般結構,並特別注意下列事項:In order to have a successful multi-identity restore, you must follow the general structure provided in this code sample with special attention to the following:

  1. 您必須利用 while(data.readNextHeader())* 迴圈以完整瀏覽備份實體。You must utilize a while(data.readNextHeader())* loop to go through the backup entities.

  2. data.getKey()* 不符合您於 onBackup 中所撰寫的索引鍵,您必須呼叫 data.skipEntityData()You must call data.skipEntityData() if data.getKey()* does not match the key you wrote in onBackup. 若沒有執行此步驟,您的還原可能會失敗。Without performing this step, your restores may not succeed.

  3. 避免在 while(data.readNextHeader())* 建構中取用備份實體時進行傳回,因為這會遺失自動寫入的實體。Avoid returning while consuming backup entities in the while(data.readNextHeader())* construct, as the entities we automatically write will be lost.

  • 其中 data 是在還原時傳遞至您應用程式之 BackupDataInput 的區域變數名稱。Where data is the local variable name for the BackupDataInput that is passed to your app upon restore.

多重身分識別 (選擇性)Multi-identity (optional)

概觀Overview

Intune App SDK 預設會將原則套用至應用程式整體。By default, the Intune App SDK will apply policy to the app as a whole. 多重身分識別為選擇性的 Intune 應用程式保護功能,可以啟用以允許將原則套用至每個身分識別。Multi-identity is an optional Intune app protection feature which can be enabled to allow policy to be applied on a per-identity level. 這需要的應用程式參與明顯高於其他應用程式保護功能。This requires significantly more app participation than other app protection features.

當應用程式想要變更作用中身分識別時,「必須」通知 SDK。The app must inform the SDK when it intends to change the active identity. 有時候,需要身分識別變更時,SDK 也會通知應用程式。In some cases, the SDK will also notify the app when an identity change is required. 但在大部分情況下,MAM 無法知道哪些資料會於指定的時間顯示在 UI 中或用在執行緒上,依賴應用程式設定正確的身分識別,才能避免資料洩漏。In most cases, however, MAM cannot know what data is being displayed in the UI or used on a thread at a given time and relies on the app to set the correct identity in order to avoid data leak. 在接下來的各節中,會呼叫某些需要應用程式動作的特定案例。In the sections that follow, some particular scenarios which require app action will be called out.

注意

缺乏正確的應用程式參與,會導致資料洩漏和其他安全性問題。A lack of the correct app participation can result in data leaks and other security issues.

使用者註冊裝置或應用程式之後,SDK 會註冊這個身分識別,並將其視為主要的 Intune 受管理身分識別。Once the user enrolls the device or the app, the SDK registers this identity and considers it the primary Intune managed identity. 應用程式中的其他使用者則會被視為未受管理,並具有不受限制的原則設定。Other users in the app will be treated as unmanaged, with unrestricted policy settings.

注意

目前,每個裝置上僅支援一個 Intune 受管理身分識別。Currently, only one Intune managed identity is supported per device.

請注意,身分識別只會定義為字串。Note that an identity is simply defined as a string. 身分識別「不區分大小寫」,而且針對身分識別對 SDK 所做出的要求,可能不會傳回原本設定身分識別時所使用的相同大小寫。Identities are case-insensitive, and requests to the SDK for an identity may not return the same casing that was originally used when setting the identity.

啟用多重身分識別Enabling Multi-identity

根據預設,所有應用程式都會視為單一身分識別應用程式。By default, all apps are considered to be single-identity apps. 您可以藉由將下列中繼資料置於 AndroidManifest.xml 中,來宣告該應用程式可感知多重身分識別。You can declare an app to be multi-identity aware by placing the following metadata in AndroidManifest.xml.

  <meta-data
    android:name="com.microsoft.intune.mam.MAMMultiIdentity"
    android:value="true" />

設定身分識別Setting the Identity

開發人員可以將應用程式使用者的身分識別設定為下列層級 (以遞減的優先順序排列):Developers can set the identity of the app user on the following levels in descending priority:

  1. 執行緒層級Thread level
  2. 內容 (通常是活動) 層級Context (generally Activity) level
  3. 處理程序層級Process level

設定為執行緒層級的身分識別會取代設定為內容層級的身分識別,而設定為內容層級的身分識別則會取代設定為處理程序層級的身分識別。An identity set at the thread level supersedes an identity set at the Context level, which supersedes an identity set at the process level. 只有在適當的相關案例中,才會使用內容上所設定的身分識別。An identity set on a Context is only used in appropriate associated scenarios. 例如,檔案 IO 操作沒有相關聯的內容。File IO operations, for example, do not have an associated Context. 最常見的情況是,應用程式會在活動上設定內容身分識別。Most commonly, apps will set the Context identity on an Activity. 應用程式「絕不」顯示受管理身分識別的資料,除非活動的身分識別設定為相同的身分識別。An app must not display data for a managed identity unless the Activity's identity is set to that same identity. 一般情況下,只有當應用程式在所有執行緒上一次只處理一名使用者時,處理序層級的身分識別才有用。In general, the process-level identity is only useful if the app works only with a single user at a time on all threads. 許多應用程式可能不需要使用它。Many apps may not need to make use of it.

您可以使用 MAMPolicyManager 中的下列方法來設定身分識別,並擷取之前設定的身分識別值。The following methods in MAMPolicyManager may be used to set the identity and retrieve the identity values previously set.

  public static void setUIPolicyIdentity(final Context context, final String identity, final MAMSetUIIdentityCallback mamSetUIIdentityCallback);

  public static String getUIPolicyIdentity(final Context context);

  public static MAMIdentitySwitchResult setProcessIdentity(final String identity);

  public static String getProcessIdentity();

  public static MAMIdentitySwitchResult setCurrentThreadIdentity(final String identity);

  public static String getCurrentThreadIdentity();

  /**
   * Get the currently applicable app policy. Same as
   * MAMComponents.get(AppPolicy.class). This method does
   * not take the context identity into account.
   */
  public static AppPolicy getPolicy();

  /**
  * Get the current app policy. This does NOT take the UI (Context) identity into account.
   * If the current operation has any context (e.g. an Activity) associated with it, use the overload below.
   */
  public static AppPolicy getPolicy(final Context context);


  public static AppPolicy getPolicyForIdentity(final String identity);

  public static boolean getIsIdentityManaged(final String identity);

注意

您可以透過將它設定為 null 來清除應用程式的身分識別。You can clear the identity of the app by setting it to null.

空字串可以做為永遠都不會具有應用程式保護原則的身分識別使用。The empty string may be used as an identity that will never have app protection policy.

結果Results

用來設定身分識別的所有方法都會透過 MAMIdentitySwitchResult 回報結果值。All the methods used to set the identity report back result values via MAMIdentitySwitchResult. 有四個可能傳回的值:There are four values that can be returned:

傳回值Return value 案例Scenario
SUCCEEDEDSUCCEEDED 身分識別變更成功。The identity change was successful.
NOT_ALLOWEDNOT_ALLOWED 不允許身分識別變更。The identity change is not allowed. 不允許身分識別變更。The identity change is not allowed. 在目前執行緒上已設定不同身分識別的情況下,嘗試設定 UI (內容) 身分識別,就會發生此情況。This occurs if an attempt is made to set the UI (Context) identity when a different identity is set on the current thread.
CANCELLEDCANCELLED 使用者已取消身分識別變更,通常是透過於 PIN 或驗證提示上按下 [返回] 按鈕。The user cancelled the identity change, generally by pressing the back button on a PIN or authentication prompt.
FAILEDFAILED 不明原因導致身分識別變更失敗。The identity change failed for an unspecified reason.

應用程式「必須」確保身分識別順利切換,再顯示或使用公司資料。The app must ensure that an identity switch is successful before displaying or using corporate data. 目前,處理序和執行緒身分識別切換在啟用多身分識別的應用程式上一直都很成功,但我們保留新增失敗狀況的權利。Currently, process and thread identity switches will always succeed for a multi-identity-enabled app, however we reserve the right to add failure conditions. 如果與執行緒身分識別發生衝突,或是使用者因為條件式啟動需求而取消 (例如按下 PIN 畫面的 [上一步] 按鈕),無效引數的 UI 身分識別切換可能失敗。The UI identity switch may fail for invalid arguments, if it would conflict with the thread identity, or if the user cancels out of conditional launch requirements (e.g. presses the back button on the PIN screen).

如果設定內容身分識別,則會以非同步方式報告結果。In the case of setting a Context identity, the result is reported asynchronously. 如果內容是活動,在執行條件式啟動之前 (可能需要使用者輸入 PIN 或公司認證),SDK 將無法得知身分識別變更是否成功。If the Context is an Activity, the SDK doesn't know if the identity change succeeded until after conditional launch is performed -- which may require the user to enter a PIN or corporate credentials. 應用程式必須實作 MAMSetUIIdentityCallback 以接收此結果,您可以針對此參數傳遞 null。The app is expected to implement a MAMSetUIIdentityCallback to receive this result, you can pass null for this parameter.

    public interface MAMSetUIIdentityCallback {
        void notifyIdentityResult(MAMIdentitySwitchResult identitySwitchResult);
  }

您也可以直接透過 MAMActivity 中的方法來設定活動的身分識別,而不是呼叫 MAMPolicyManager.setUIPolicyIdentityYou can also set the identity of an activity directly through a method in MAMActivity instead of calling MAMPolicyManager.setUIPolicyIdentity. 請使用下列方法來達成:Use following method to do so:

     public final void switchMAMIdentity(final String newIdentity);

您也可以覆寫 MAMActivity 中的方法,以使應用程式能收到嘗試變更該活動身分識別的結果通知。You can also override a method in MAMActivity if you want the app to be notified of the result of attempts to change the identity of that activity.

    public void onSwitchMAMIdentityComplete(final MAMIdentitySwitchResult result);

注意

切換身分識別可能會需要重新建立活動。Switching the identity may require recreating the activity. 在此情況下,onSwitchMAMIdentityComplete 回呼會傳遞至活動的新執行個體。In this case, the onSwitchMAMIdentityComplete callback will be delivered to the new instance of the activity.

隱含身分識別變更Implicit Identity Changes

除了應用程式設定身分識別的能力之外,執行緒或內容的身分識別也可能會根據來自另一個具有應用程式保護原則的「可搭配 Intune 的應用程式」的資料輸入而變更。In addition to the app's ability to set the identity, a thread or a context's identity may change based on data ingress from another Intune-enlightened app that has app protection policy.

範例Examples

  1. 如果活動是根據另一個 MAM 應用程式所傳送的 Intent 來啟動,就會根據另一個應用程式在傳送 Intent 時的有效身分識別,來設定活動的身分識別。If an activity is launched from an Intent sent by another MAM app, the activity’s identity will be set based on the effective identity in the other app at the point the Intent was sent.

  2. 針對服務,執行緒的身分識別會在 onStartonBind 呼叫期間以類似的方式進行設定。For services, the thread identity will be set similarly for the duration of an onStart or onBind call. 針對從 onBind 傳回之 Binder 的呼叫,也會暫時設定執行緒身分識別。Calls into the Binder returned from onBind will also temporarily set the thread identity.

  3. 呼叫 ContentProvider 同樣會在該期間設定執行緒身分識別。Calls into a ContentProvider will similarly set the thread identity for their duration.

此外,使用者與活動互動可能會導致隱含身分識別切換。In addition, user interaction with an activity may cause an implicit identity switch.

範例:使用者在 Resume 期間取消授權提示,將會導致隱含切換至空的身分識別。Example: A user canceling out of an authorization prompt during Resume will result in an implicit switch to an empty identity.

應用程式會有機會注意到這些變更,並可以在必要的情況下禁止變更。The app is given an opportunity to be made aware of these changes, and, if it must, the app can forbid them. MAMServiceMAMContentProvider 會公開下列可由子類別覆寫的方法:MAMService and MAMContentProvider expose the following method that subclasses may override:

public void onMAMIdentitySwitchRequired(final String identity,
  final AppIdentitySwitchResultCallback callback);

MAMActivity 類別中,方法中會出現額外的參數:In the MAMActivity class , an additional parameter is present in the method:

public void onMAMIdentitySwitchRequired(final String identity,
  final AppIdentitySwitchReason reason,
  final AppIdentitySwitchResultCallback callback);
  • AppIdentitySwitchReason 會擷取隱含切換的來源,並可接受 CREATERESUME_CANCELLEDNEW_INTENT 值。The AppIdentitySwitchReason captures the source of the implicit switch, and can accept the values CREATE, RESUME_CANCELLED, and NEW_INTENT. 當活動繼續導致顯示 PIN、驗證或其他合規性 UI,而且使用者嘗試取消該 UI (通常是透過使用 [上一頁] 按鈕) 時,就會使用 RESUME_CANCELLED 原因。The RESUME_CANCELLED reason is used when activity resume causes PIN, authentication, or other compliance UI to be displayed and the user attempts to cancel out of that UI, generally though use of the back button.

  • AppIdentitySwitchResultCallback 如下所示:The AppIdentitySwitchResultCallback is as follows:

    public interface AppIdentitySwitchResultCallback {
        /**
         * @param result
         *            whether the identity switch can proceed.
         */
        void reportIdentitySwitchResult(AppIdentitySwitchResult result);
    }
    

    其中 AppIdentitySwitchResult 會是 SUCCESS 或 FAILURE。Where AppIdentitySwitchResult is either SUCCESS or FAILURE.

針對所有隱含身分識別變更會呼叫 onMAMIdentitySwitchRequired 方法 (透過從 MAMService.onMAMBind 傳回的 Binder 進行的變更除外)。The method onMAMIdentitySwitchRequired is called for all implicit identity changes except for those made through a Binder returned from MAMService.onMAMBind. onMAMIdentitySwitchRequired 的預設實作會立即呼叫:The default implementations of onMAMIdentitySwitchRequired immediately call:

  • reportIdentitySwitchResult(FAILURE) (當原因為 RESUME_CANCELLED 時)。reportIdentitySwitchResult(FAILURE) when the reason is RESUME_CANCELLED.

  • reportIdentitySwitchResult(SUCCESS) (針對所有其他情況)。reportIdentitySwitchResult(SUCCESS) in all other cases.

    大多數應用程式應該不會需要透過不同方式來封鎖或延遲身分識別切換,但如果應用程式需要這樣做,則必須考慮下列重點:It is not expected that most apps will need to block or delay an identity switch in a different manner, but if an app needs to do so, the following points must be considered:

    • 如果身分識別切換遭到封鎖,則結果與 Receive 共用設定禁止資料輸入相同。If an identity switch is blocked, the result is the same as if Receive sharing settings had prohibited the data ingress.

    • 如果服務正在主執行緒上執行,則「必須」同步呼叫 reportIdentitySwitchResult,否則 UI 執行緒將會停止回應。If a Service is running on the main thread, reportIdentitySwitchResult must be called synchronously or the UI thread will hang.

    • 若要建立「活動」,會在 onMAMCreate 之前呼叫 onMAMIdentitySwitchRequiredFor Activity creation, onMAMIdentitySwitchRequired will be called before onMAMCreate. 如果應用程式必須顯示 UI,以判斷是否允許身分識別切換,則必須使用「不同」的活動顯示該 UI。If the app must show UI to determine whether to allow the identity switch, that UI must be shown using a different activity.

    • 在「活動」中,如果因 RESUME_CANCELLED 的原因而要求切換至空的身分識別,則應用程式必須修改恢復的活動,以顯示與該身分識別切換一致的資料。In an Activity, when a switch to the empty identity is requested with the reason as RESUME_CANCELLED, the app must modify the resumed activity to display data consistent with that identity switch. 如果不可行,應用程式應該拒絕切換,並會再次要求使用者符合恢復之身分識別的原則 (例如,藉由顯示應用程式 PIN 輸入畫面)。If this is not possible, the app should refuse the switch, and the user will be asked again to comply with policy for the resuming identity (e.g. by being presented with the app PIN entry screen).

      注意

      多重身分識別應用程式永遠會從受管理和未受管理的應用程式接收內送資料。A multi-identity app will always receive incoming data from both managed and unmanaged apps. 應用程式會負責以受管理的方式來處理受管理身分識別中的資料。It is the responsibility of the app to treat data from managed identities in a managed manner.

    如果要求的身分識別是受管理的 (可使用 MAMPolicyManager.getIsIdentityManaged 檢查),但應用程式無法使用該帳戶 (例如,因為必須先在應用程式中設定如電子郵件帳戶等的帳戶),則應該拒絕身分識別切換。If a requested identity is managed (use MAMPolicyManager.getIsIdentityManaged to check), but the app is not able to use that account (e.g. because accounts, such as email accounts, must be set up in the app first) then the identity switch should be refused.

檔案保護File Protection

每個檔案都有建立時根據執行緒和處理程序身分識別而來的相關聯身分識別。Every file has an identity associated with it at the time of creation, based on thread and process identity. 此身分識別將會用於檔案加密和選擇性抹除。This identity will be used for both file encryption and selective wipe. 只有其身分識別為受管理且具有需要加密之原則的檔案才會進行加密。Only files whose identity is managed and has policy requiring encryption will be encrypted. SDK 的預設選擇性功能抹除,只會抹除與已要求抹除之受管理身分識別相關聯的檔案。The SDK's default selective functionality wipe will only wipe files associated with the managed identity for which a wipe has been requested. 應用程式可使用 MAMFileProtectionManager 類別來查詢或變更檔案的身分識別。The app may query or change a file’s identity using the MAMFileProtectionManager class.

  public final class MAMFileProtectionManager {
  /**
       * Protect a file. This will synchronously trigger whatever protection is required for the 
         file, and will tag the file for future protection changes.

       *
       * @param identity
       *            Identity to set.
       * @param file
       *            File to protect.
       * @throws IOException
       *             If the file cannot be changed.
       */
      public static void protect(final File file, final String identity) throws IOException;

      /**
      * Protect a file obtained from a content provider. This is intended to be used for
      * sdcard (whether internal or removable) files accessed through the Storage Access Framework.
      * It may also be used with descriptors referring to private files owned by this app.
      * It is not intended to be used for files owned by other apps and such usage will fail. If
      * creating a new file via a content provider exposed by another MAM-integrated app, the new
      * file identity will automatically be set correctly if the ContentResolver in use was
      * obtained via a Context with an identity or if the thread identity is set.
      *
      * This will synchronously trigger whatever protection is required for the file, and will tag
      * the file for future protection changes. If an identity is set on a directory, it is set
      * recursively on all files and subdirectories. If MAM is operating in offline mode, this
      * method will silently do nothing.
      *
      * @param identity
      *       Identity to set.
      * @param file
      *       File to protect.
      *
      * @throws IOException
      *       If the file cannot be protected.

      */
      public static void protect(final ParcelFileDescriptor file, final String identity) throws IOException;

      /**
       * Get the protection info on a file.
       *
       * @param file
       *            File or directory to get information on.
       * @return File protection info, or null if there is no protection info.
       * @throws IOException
       *             If the file cannot be read or opened.
       */
      public static MAMFileProtectionInfo getProtectionInfo(final ParcelFileDescriptor file) throws IOException;

  }

  public interface MAMFileProtectionInfo {
      String getIdentity();
  }

應用程式責任App Responsibility

MAM 無法自動推斷在 Activity 中被讀取的檔案和顯示的資料之間的關聯性。MAM cannot automatically infer a relationship between files being read and data being displayed in an Activity. 應用程式「必須」先適當地設定 UI 身分識別,才能顯示公司資料。Apps must set the UI identity appropriately before displaying corporate data. 這包括從檔案讀取的資料。This includes data read from files. 如果檔案來自應用程式之外 (來自 ContentProvider 或讀取自公開寫入位置),應用程式「必須」嘗試先判斷檔案身分識別 (使用 MAMFileProtectionManager.getProtectionInfo) 才能顯示從檔案讀取的資訊。If a file comes from outside the app (either from a ContentProvider or read from a publicly writable location), the app must attempt to determine the file identity (using MAMFileProtectionManager.getProtectionInfo) before displaying information read from the file. 如果 getProtectionInfo 回報非 null、非空白的身分識別,則 UI 身分識別「必須」設定成符合此身分識別 (使用 MAMActivity.switchMAMIdentityMAMPolicyManager.setUIPolicyIdentity)。If getProtectionInfo reports a non-null, non-empty identity, the UI identity must be set to match this identity (using MAMActivity.switchMAMIdentity or MAMPolicyManager.setUIPolicyIdentity). 如果身分識別切換失敗,「絕無法」顯示檔案中的資料。If the identity switch fails, data from the file must not be displayed.

範例流程可能看起來像這樣:An example flow might look something like the following:

  • 使用者選取要在應用程式中開啟的文件User selects a document to open in the app
  • 在開啟流程的過程中,還未從磁碟讀取資料之前,應用程式會確認顯示內容應該使用的身分識別。During the open flow, prior to reading data from disk, the app confirms the identity that should be used to display the content
    • MAMFileProtectionInfo info = MAMFileProtectionManager.getProtectionInfo(docPath)MAMFileProtectionInfo info = MAMFileProtectionManager.getProtectionInfo(docPath)
    • if(info) MAMPolicyManager.setUIPolicyIdentity(activity, info.getIdentity(), callback)if(info) MAMPolicyManager.setUIPolicyIdentity(activity, info.getIdentity(), callback)
    • 應用程式等待回報給回呼的結果The app waits until a result is reported to callback
    • 如果報告的結果是失敗,應用程式就不會顯示文件。If the reported result is a failure, the app does not display the document.
  • 應用程式會開啟並轉譯檔案The app opens and renders the file

離線案例Offline Scenarios

離線模式需要檔案身分識別標記。File identity tagging is sensitive to offline mode. 下列各點應該列入考量:The following points should be taken into account:

  • 如果未安裝公司入口網站,則無法標記檔案的身分識別。If the Company Portal is not installed, files cannot be identity-tagged.

  • 如果已安裝公司入口網站,但應用程式沒有 Intune MAM 原則,則檔案將無法確實標記身分識別。If the Company Portal is installed, but the app does not have Intune MAM policy, files cannot be reliably tagged with identity.

  • 當檔案身分識別標記變成可用時,所有先前建立的檔案都會視為個人/未受管理 (屬於空字串身分識別),除非應用程式之前已安裝為受單一身分識別管理的應用程式,在此情況下則會將它們視為屬於已註冊的使用者。When file identity tagging becomes available, all previously created files are treated as personal/unmanaged (belonging to the empty-string identity) unless the app was previously installed as a single-identity managed app in which case they are treated as belonging to the enrolled user.

目錄保護Directory Protection

目錄保護可以使用和保護檔案相同的 protect 方法來進行保護。Directories may be protected using the same protect method used to protect files. 請注意,目錄保護會以遞迴方式套用至目錄中的所有檔案和子目錄,以及在目錄內新建立的檔案上。Please note that directory protection applies recursively to all files and subdirectories contained in the directory, and to new files created within the directory. 由於目錄保護是以以遞迴方式套用,針對非常大的目錄,protect 呼叫可能需要花費一些時間才能完成。Because directory protection is applied recursively, the protect call can take some time to complete for very large directories. 基於那個原因,若應用程式要將保護套用至含有大量檔案的目錄,我們建議在背景執行緒上以非同步方式執行 protectFor that reason, apps applying protection to a directory that contains a large number of files might wish to run protect asynchronously on a background thread.

資料保護Data Protection

您無法將檔案標記為屬於多重身分識別。It is not possible to tag a file as belonging to multiple identities. 如果應用程式必須將屬於不同使用者的資料儲存到同一個檔案,則可以使用 MAMDataProtectionManager 所提供的功能手動執行這項操作。Apps that must store data belonging to different users in the same file can do so manually, using the features provided by MAMDataProtectionManager. 這可讓應用程式加密資料,並將它繫結至特定的使用者。This allows the app to encrypt data and tie it to a particular user. 加密資料適合存放到磁碟的檔案中。The encrypted data is suitable for storing to disk in a file. 您可以查詢與身分識別相關聯的資料,並於稍後解密資料。You can query the data associated with the identity and the data can be unecrypted later.

會運用 MAMDataProtectionManager 的應用程式,應該實作針對 MANAGEMENT_REMOVED 通知的接收器。Apps which make use of MAMDataProtectionManager should implement a receiver for the MANAGEMENT_REMOVED notification. 如果透過此類別獲得保護的緩衝區在受到保護期間有啟用檔案加密,在此通知完成之後,該緩衝區將會無法讀取。After this notification completes, buffers which were protected via this class will no longer be readable if file encryption was enabled when the buffers were protected. 應用程式可以透過在此通知期間於所有緩衝區上呼叫 MAMDataProtectionManager.unprotect 來補救此情況。An app can remediate this situation by calling MAMDataProtectionManager.unprotect on all buffers during this notification. 請注意,若想要保留身分識別資訊,也可以在此通知期間呼叫保護 (加密在通知期間一定會停用)。Note that it is also safe to call protect during this notification if it is desired to preserve identity information -- encryption is guaranteed to be disabled during the notification.


public final class MAMDataProtectionManager {
    /**
     * Protect a stream. This will return a stream containing the protected
     * input.
     *
     * @param identity
     *            Identity to set.
     * @param input
     *            Input data to protect, read sequentially. This function
     *            will change the position of the stream but may not have
     *            read the entire stream by the time it returns. The
     *            returned stream will wrap this one. Calls to read on the
     *            returned stream may cause further reads on the original
     *            input stream. Callers should not expect to read directly
     *            from the input stream after passing it to this method.
     *            Calling close on the returned stream will close this one.
     * @return Protected input data.
     * @throws IOException
     *             If the data could not be protected
     */
    public static InputStream protect(final InputStream input, final String identity);

    /**
     * Protect a byte array. This will return protected bytes.
     *
     * @param identity
     *            Identity to set.
     * @param input
     *            Input data to protect.
     * @return Protected input data.
     * @throws IOException
     *             If the data could not be protected
     */
    public static byte[] protect(final byte[] input, final String identity) throws IOException;

    /**
     * Unprotect a stream. This will return a stream containing the
     * unprotected input.
     *
     * @param input
     *            Input data to protect, read sequentially.
     * @return Protected input data.
     * @throws IOException
     *             If the data could not be unprotected
     */
    public static InputStream unprotect(final InputStream input) throws IOException;

    /**
     * Unprotect a byte array. This will return unprotected bytes.
     *
     * @param input
     *            Input data to protect.
     * @return Protected input data.
     * @throws IOException
     *             If the data could not be unprotected
     */
    public static byte[] unprotect(final byte[] input) throws IOException;

    /**
     * Get the protection info on a stream.
     *
     * @param input
     *            Input stream to get information on. Either this input
     *            stream must have been returned by a previous call to
     *            protect OR input.markSupported() must return true.
     *            Otherwise it will be impossible to get protection info
     *            without advancing the stream position. The stream must be
     *            positioned at the beginning of the protected data.
     * @return Data protection info, or null if there is no protection
     *            info.
     * @throws IOException
     *             If the input cannot be read.
     */
    public static MAMDataProtectionInfo getProtectionInfo(final InputStream input) throws IOException;

    /**
     * Get the protection info on a stream.
     *
     * @param input
     *            Input bytes to get information on. These must be bytes
     *            returned by a previous call to protect() or a copy of
     *            such bytes.
     * @return Data protection info, or null if there is no protection
     *            info.
     * @throws IOException
     *             If the input cannot be read.
     */
    public static MAMDataProtectionInfo getProtectionInfo(final byte[] input) throws IOException;
}

內容提供者Content Providers

如果應用程式透過 ContentProvider 提供 ParcelFileDescriptor 以外的公司資料,該應用程式必須在 MAMContentProvider 中呼叫 isProvideContentAllowed(String) 方法,並針對內容傳遞擁有者身分識別的 UPN (使用者主體名稱)。If the app provides corporate data other than a ParcelFileDescriptor through a ContentProvider, the app must call the method isProvideContentAllowed(String) in MAMContentProvider, passing the owner identity's UPN (user principal name) for the content. 如果此函數傳回 false,內容「可能不會」傳回給呼叫者。If this function returns false, the content may not be returned to the caller. 透過內容提供者傳回的檔案描述元會自動根據檔案身分識別進行處理。File descriptors returned through a content provider are handled automatically based on the file identity.

選擇性抹除Selective Wipe

如果應用程式註冊 WIPE_USER_DATA 通知,它將無法取得 SDK 預設選擇性抹除行為的好處。If an app registers for the WIPE_USER_DATA notification, it will not receive the benefit of the SDK's default selective wipe behavior. 針對感知多重身分識別的應用程式,此影響可能更為明顯,因為 MAM 預設選擇性抹除只會抹除其身分識別為抹除目標的檔案。For multi-identity aware apps, this loss may be more significant since MAM default selective wipe will wipe only files whose identity is targeted by a wipe.

若多重身分識別感知應用程式想要執行 MAM 預設選擇性抹除,「且」_想要在抹除上執行自己的動作,便應該註冊 WIPE_USER_AUXILIARY_DATA 通知。If a multi-identity aware application wishes MAM default selective wipe to be done and_ wishes to perform its own actions on wipe, it should register for WIPE_USER_AUXILIARY_DATA notifications. SDK 會立即傳送這項通知,再執行 MAM 預設選擇性抹除。This notification will be sent immediately by the SDK before it performs the MAM default selective wipe. 應用程式一律不應同時註冊 WIPE_USER_DATA 和 WIPE_USER_AUXILIARY_DATA。An app should never register for both WIPE_USER_DATA and WIPE_USER_AUXILIARY_DATA.

啟用 Android 應用程式的 MAM 目標設定 (選擇性)Enabling MAM targeted configuration for your Android applications (optional)

您可在 Intune 主控台中設定應用程式特定的機碼值組。Application-specific key-value pairs may be configured in the Intune console. Intune 完全不解譯這些機碼值組,僅傳遞給應用程式。These key-value pairs are not interpreted by Intune at all, but are simply passed on to the app. 想要接收這類設定的應用程式可以使用 MAMAppConfigManagerMAMAppConfig 類別來執行作業。Applications which want to receive such configuration can use the MAMAppConfigManager and MAMAppConfig classes to do so. 如有多個原則以相同的應用程式為目標,相同的機碼可能會有多個衝突值。If multiple policies are targeted at the same app, there may be multiple conflicting values available for the same key.

範例Example

MAMAppConfigManager configManager = MAMComponents.get(MAMAppConfigManager.class);
String identity = "user@contoso.com"
MAMAppConfig appConfig = configManager.getAppConfig(identity);
LOGGER.info("App Config Data = " + (appConfig == null ? "null" : appConfig.getFullData()));
String valueToUse = null;
if (appConfig.hasConflict("foo")) {
    List<String> values = appConfig.getAllStringsForKey("foo");
    for (String value : values) {
        if (isCorrectValue(value)) {
            valueToUse = value;
        }
    }
} else {
    valueToUse = appConfig.getStringForKey("foo", MAMAppConfig.StringQueryType.Any);
}
LOGGER.info("Found value " + valueToUse);

MAMAppConfig 參考MAMAppConfig Reference

public interface MAMAppConfig {
    /**
     * Conflict resolution types for Boolean values.
     */
    enum BooleanQueryType {
        /**
         * In case of conflict, arbitrarily picks one. This is not guaranteed to return the same value every time.
         */
        Any,
        /**
         * In case of conflict, returns true if any of the values are true.
         */
        Or,
        /**
         * In case of conflict, returns false if any of the values are false.
         */
        And
    }

    /**
     * Conflict resolution types for integer and double values.
     */
    enum NumberQueryType {
        /**
         * In case of conflict, arbitrarily picks one. This is not guaranteed to return the same value every time.
         */
        Any,
        /**
         * In case of conflict, returns the minimum Integer.
         */
        Min,
        /**
         * In case of conflict, returns the maximum Integer.
         */
        Max
    }

    /**
     * Conflict resolution types for Strings.
     */
    enum StringQueryType {
        /**
         * In case of conflict, arbitrarily picks one. This is not guaranteed to return the same value every time.
         */
        Any,
        /**
         * In case of conflict, returns the first result ordered alphabetically.
         */
        Min,
        /**
         * In case of conflict, returns the last result ordered alphabetically.
         */
        Max
    }

    /**
     * Retrieve the List of Dictionaries containing all the custom
     *  config data sent by the MAMService. This will return every
     * Application Configuration setting available for this user, one
     *  mapping for each policy applied to the user.
     */
    List<Map<String, String>> getFullData();

    /**
     * Returns true if there is more than one targeted custom config setting for the key provided. 
     */
    boolean hasConflict(String key);

    /**
     * @return a Boolean value for the given key if it can be coerced into a Boolean, or 
     * null if none exists or it cannot be coerced.
     */
    Boolean getBooleanForKey(String key, BooleanQueryType queryType);

    /**
     * @return a Long value for the given key if it can be coerced into a Long, or null if none exists or it cannot be coerced.
     */
    Long getIntegerForKey(String key, NumberQueryType queryType);

    /**
     * @return a Double value for the given key if it can be coerced into a Double, or null if none exists or it cannot be coerced.
     */
    Double getDoubleForKey(String key, NumberQueryType queryType);

    /**
     * @return a String value for the given key, or null if none exists.
     */
    String getStringForKey(String key, StringQueryType queryType);

    /**
     * Like getBooleanForKey except returns all values if multiple are present.
     */
    List<Boolean> getAllBooleansForKey(String key);

    /**
     * Like getIntegerForKey except returns all values if multiple are present.
     */
    List<Long> getAllIntegersForKey(String key);

    /**
     * Like getDoubleForKey except returns all values if multiple are present.
     */
    List<Double> getAllDoublesForKey(String key);

    /**
     * Like getStringForKey except returns all values if multiple are present.
     */
    List<String> getAllStringsForKey(String key);
}

通知Notification

應用程式設定新增新的通知類型:App config adds a new notification type:

  • REFRESH_APP_CONFIG:這個通知是在 MAMUserNotification 中傳送,通知應用程式,確定應用程式有新的應用程式設定資料可用。REFRESH_APP_CONFIG: This notification is sent in a MAMUserNotification and informs the app that new app config data is available.

如需圖形 API 與 MAM 目標設定值有關之功能的詳細資訊,請參閱 Graph API Reference MAM Targeted Config (圖形 API 參考 MAM 目標設定)。For more information about the capabilities of the Graph API with respect to the MAM targeted configuration values, see Graph API Reference MAM Targeted Config.

如需如何在 Android 建立 MAM 目標應用程式設定原則的詳細資訊,請參閱如何使用 Android for Work 適用的 Microsoft Intune 應用程式設定原則中有關 MAM 目標應用程式設定的一節。For more information about how to create a MAM targeted app configuration policy in Android, see the section on MAM targeted app config in How to use Microsoft Intune app configuration policies for Android.

樣式自訂 (選擇性)Style Customization (optional)

您可以對由 MAM SDK 產生的檢視進行視覺上的自訂,以使它能更加符合所整合的目標應用程式。Views generated by the MAM SDK can be visually customized to more closely match the app in which it is integrated. 您可以自訂主要、次要及背景色彩,以及應用程式標誌的大小。You can customize primary, secondary, and background colors, as well as the size of the app logo. 此樣式自訂為選擇性,若沒有設定任何自訂樣式,系統將會使用預設值。This style customization is optional and defaults will be used if no custom style is configured.

如何自訂How to customize

若要將樣式變更套用至 Intune MAM 檢視,您必須先建立樣式覆寫 XML 檔案。In order to have style changes apply to the Intune MAM views, you must first create a style override XML file. 此檔案必須置於應用程式的 "/res/xml" 目錄,您可以任意命名檔案。This file should be placed in the “/res/xml” directory of your app and you may name it whatever you like. 下列為此檔案必須遵循之格式的範例。Below is an example of the format this file needs to follow.

<?xml version="1.0" encoding="utf-8"?>
<styleOverrides>
    <item
        name="foreground_color"
        resource="@color/red"/>
    <item
        name="accent_color"
        resource="@color/blue"/>
    <item
        name="background_color"
        resource="@color/green"/>
    <item
        name="logo_image"
        resource="@drawable/app_logo"/>
</styleOverrides>

您必須重複使用已存在於應用程式內的資源。You must reuse resources that already exist within your app. 例如,您必須在 colors.xml 檔案中定義綠色的色彩,並在此參考它。For example, you must define the color green in the colors.xml file and reference it here. 您不能使用十六進位色彩代碼 "#0000ff"。You cannot use the Hex color code “#0000ff." 應用程式標誌的大小上限為 110 DIP (DP)。The maximum size for the app logo is 110 dip (dp). 您可以使用較小的標誌影像,但符合大小上限的影像將能提供最佳的外觀。You may use a smaller logo image, but adhering to the maximum size will yield the best looking results. 如果您超過 110 DIP 的限制,該影像將會縮小並可能變得模糊。If you exceed the 110 dip limit, the image will scale down and possibly cause blurring.

以下為允許的樣式屬性、它們所控制的 UI 元素、其 XML 屬性項目名稱,以及每個屬性所預期之資源類型的完整清單。Below is the complete list of allowed style attributes, the UI elements they control, their XML attribute item names, and the type of resource expected for each.

樣式屬性Style attribute 受影響的 UI 元素UI elements affected 屬性項目名稱Attribute item name 預期的資源類型Expected resource type
背景色彩Background color PIN 畫面背景色彩PIN screen background color
PIN 方塊填滿色彩PIN box fill color
background_colorbackground_color ColorColor
前景色彩Foreground color 前景文字色彩Foreground text color
預設狀態的 PIN 方塊邊界PIN box border in default state
使用者輸入 PIN 時的 PIN 方塊字元 (包含模糊字元)Characters (including obfuscated characters) in PIN box when user enters a PIN
foreground_colorforeground_color ColorColor
輔色Accent color 反白顯示時的 PIN 方塊邊界PIN box border when highlighted
超連結Hyperlinks
accent_coloraccent_color ColorColor
應用程式標誌App logo 顯示在 Intune 應用程式 PIN 畫面的大型標誌Large icon that appears in the Intune app PIN screen logo_imagelogo_image DrawableDrawable

限制Limitations

檔案大小限制File Size limitations

針對沒有搭配 ProGuard (英文) 執行的大型程式碼基底,Dalvik 可執行檔格式的限制將會造成問題。For large code bases that run without ProGuard, the limitations of the Dalvik executable file format become an issue. 具體來說,可能會發生下列限制:Specifically, the following limitations may occur:

  1. 65K 的欄位限制。The 65K limit on fields.
  2. 65K 的方法限制。The 65K limit on methods.

原則強制執行限制Policy enforcement limitations

  • 螢幕擷取:SDK 無法強制執行 Activity 中已經透過 Activity.onCreate 完成的新螢幕擷取設定值。Screen Capture: The SDK is unable to enforce a new screen capture setting value in Activities that have already gone through Activity.onCreate. 這會導致應用程式已設定為停用螢幕擷取畫面一段時間,但仍可取得螢幕擷取畫面。This can result in a period of time where the app has been configured to disable screenshots but screenshots can still be taken.

  • 使用內容解析程式:「傳送或接收」Intune 原則可能會封鎖或部分封鎖內容解析程式的使用,不讓其存取另一個應用程式中的內容提供者。Using Content Resolvers: The "transfer or receive" Intune policy may block or partially block the use of a content resolver to access the content provider in another app. 這將導致 ContentResolver 方法傳回 null,或者擲回錯誤值 (例如,若受到封鎖, openOutputStream 將會擲回 FileNotFoundException )。This will cause ContentResolver methods to return null or throw a failure value (e.g. openOutputStream will throw FileNotFoundException if blocked). 應用程式可以藉由呼叫下列項目,判斷透過內容解析程式無法寫入資料是否起因於原則 (或可能由原則造成):The app can determine whether a failure to write data through a content resolver was caused by policy (or would be caused by policy) by making the call:

    MAMPolicyManager.getPolicy(currentActivity).getIsSaveToLocationAllowed(contentURI);
    

    或如果沒有相關聯的活動or if there is no associated activity

    MAMPolicyManager.getPolicy().getIsSaveToLocationAllowed(contentURI);
    

    在第二個案例中,多重身分識別應用程式必須仔細正確設定執行緒身分識別 (或將明確的身分識別傳遞給 getPolicy 呼叫)。In this second case, multi-identity apps must take care to set the thread identity appropriately (or pass an explicit identity to the getPolicy call).

匯出服務Exported services

Intune App SDK 隨附的 AndroidManifest.xml 檔案包含 MAMNotificationReceiverService,其必須為匯出的服務,才能讓公司入口網站傳送通知給可搭配 Intune 的應用程式。The AndroidManifest.xml file included in the Intune App SDK contains MAMNotificationReceiverService, which must be an exported service to allow the Company Portal to send notifications to an enlightened app. 服務會檢查呼叫者以確保僅允許公司入口網站傳送通知。The service checks the caller to ensure that only the Company Portal is allowed to send notifications.

SDK 取用者的期望Expectations of the SDK consumer

Intune SDK 會維護由 Android API 所提供的合約,但可能會因為強制執行原則,而更頻繁地觸發失敗狀況。The Intune SDK maintains the contract provided by the Android API, though failure conditions may be triggered more frequently as a result of policy enforcement. 下列 Android 最佳作法可降低失敗的可能性:These Android best practices will reduce the likelihood of failure:

  • Android SDK 函式如果可能會傳回 null,則現在為 null 的可能性更高。Android SDK functions that may return null have a higher likelihood of being null now. 若要將問題降至最低,請確定 null 檢查是在正確的位置。To minimize issues, ensure that null checks are in the right places.

  • 針對可以檢查的功能,必須透過其 MAM 取代項目 API 進行檢查。Features that can be checked for must be checked for through their MAM replacement APIs.

  • 任何衍生的函式皆必須透過其超級類別版本進行呼叫。Any derived functions must call through to their super class versions.

  • 避免以模稜兩可的方式使用任何 API。Avoid use of any API in an ambiguous way. 例如,在未檢查 requestCode 的情況下使用 Activity.startActivityForResult,將會導致奇怪的行為。For example, using Activity.startActivityForResult without checking the requestCode will cause strange behavior.

遙測Telemetry

Intune App SDK for Android 不會控制來自您應用程式的資料收集。The Intune App SDK for Android does not control data collection from your app. 公司入口網站應用程式預設會記錄遙測資料。The Company Portal application logs telemetry data by default. 這些資料會傳送到 Microsoft Intune。This data is sent to Microsoft Intune. 根據 Microsoft 原則,我們不會收集任何個人識別資訊 (PII)。As per Microsoft Policy, we do not collect any personally identifiable information (PII).

注意

如果終端使用者選擇不要傳送此資料,則必須在公司入口網站應用程式的 [設定] 下關閉遙測。If end users choose not to send this data, they must turn off telemetry under Settings on the Company Portal app. 若要深入了解,請參閱關閉 Microsoft 使用狀況資料收集To learn more, see Turn off Microsoft usage data collection.

  • 所有程式庫專案應盡可能共用相同的 android:package。All library projects should share the same android:package where possible. 這不會在執行階段偶發性地發生失敗,而純粹是建置時間問題。This will not sporadically fail in run-time; this is purely a build-time problem. 較新版本的 Intune App SDK 將會移除部分的冗餘項目。Newer versions of the Intune App SDK will remove some of the redundancy.

  • 使用最新的 Android SDK 建置工具。Use the newest Android SDK build tools.

  • 移除所有不必要和未使用的程式庫 (例如 android.support.v4)Remove all unnecessary and unused libraries (e.g. android.support.v4)