調整受管理的設定

如果您正在為企業市場開發應用程式, 以符合組織政策設定的特定需求。 受管理設定,舊稱「應用程式限制」。 允許機構的 IT 管理員從遠端指定 應用程式。這項功能對於機構核准程序特別實用 應用程式已部署至工作資料夾。

舉例來說,特定機構可能會規定需核准的應用程式 IT 管理員執行以下動作:

  • 允許或封鎖網路瀏覽器的網址
  • 設定是否允許應用程式透過行動網路同步處理內容,或僅限 透過 Wi-Fi
  • 調整應用程式的電子郵件設定

本指南說明如何在 如要查看具有受管理設定的範例應用程式,請參閱 ManagedConfigurations。 如果您是企業行動管理服務 (EMM) 開發人員,請參閱 Android Management API 指南

注意:基於歷史原因,這些設定稱為 限制,並與使用這種事件的檔案和類別一起實作 字詞 (例如 RestrictionsManager)。不過, 實際上可以執行多種設定選項 不只能限制應用程式功能

遠端設定總覽

應用程式會定義可遠端使用的受管理設定選項 是由 IT 管理員設定這些是任意設定 用戶端變更專案。如果應用程式是在工作資料夾中執行, IT 管理員可以變更應用程式的受管理設定。

受管理設定提供者是在同一部裝置上執行的另一個應用程式。 這個應用程式通常是由 IT 管理員控管。 IT 管理員向受管理的 設定提供者應用程式。該應用程式隨即會變更應用程式的設定。

如何提供外部代管的設定:

  • 在應用程式資訊清單中宣告受管理的設定。執行 因此 IT 管理員可讀取應用程式的 管理設定
  • 每當應用程式重新啟用時,請使用 RestrictionsManager 物件查看目前 將應用程式的使用者介面和行為變更為 符合這些設定
  • 監聽 ACTION_APPLICATION_RESTRICTIONS_CHANGED 意圖。收到 廣播,請查看 RestrictionsManager 以瞭解 ,並對 藉此影響應用程式行為

定義受管理的設定

應用程式可支援您定義的任何受管理設定。您宣告 並宣告為受管理的設定檔。 設定個別的設定檔建立設定檔可讓您 ,檢查應用程式提供的受管理設定。EMM 合作夥伴 可使用 Google Play API 讀取應用程式的設定。

如要定義應用程式的遠端設定選項,請加入下列元素 新增至資訊清單的 <application> 元素:

<meta-data android:name="android.content.APP_RESTRICTIONS"
    android:resource="@xml/app_restrictions" />

在應用程式的app_restrictions.xml res/xml 目錄內。這個檔案的結構說明 RestrictionsManager 的參照。這個檔案含有 單一頂層 <restrictions> 元素,其中包含 每項設定一個 <restriction> 子元素 選項。

注意:請勿建立本地化版本的 管理設定檔您的應用程式只能採用 單一受管理設定檔 確保您的應用程式在所有語言版本中保持一致

在企業環境中,EMM 通常會使用受管理的 為 IT 人員產生遠端控制台 讓管理員能從遠端設定 應用程式。

受管理設定提供者可以查詢應用程式,以尋找詳細資料 應用程式可用的設定 (包括其說明) 文字。設定供應商和 IT 管理員可以變更應用程式的 管理化設定,即使應用程式沒有執行也沒問題。

舉例來說,假設您的應用程式可從遠端設為允許或禁止 即可透過行動網路連線下載資料。應用程式可以是 <restriction> 元素如下:

<?xml version="1.0" encoding="utf-8"?>
<restrictions xmlns:android="http://schemas.android.com/apk/res/android">

  <restriction
    android:key="downloadOnCellular"
    android:title="@string/download_on_cell_title"
    android:restrictionType="bool"
    android:description="@string/download_on_cell_description"
    android:defaultValue="true" />

</restrictions>

您可以使用每項設定的 android:key 屬性 從受管理的設定套件讀取該值。因此 每項設定都必須有一個不重複的鍵字串 無法本地化。必須以字串常值指定。

注意:在正式版應用程式中,android:titleandroid:description 應從本地化資源取得 檔案, 使用資源本地化

應用程式會使用 bundle_array 內的套件定義限制。 舉例來說,如果應用程式提供多個 VPN 連線選項,就能定義每個 VPN 伺服器 擁有多個 bundle 設定檔 透過套裝組合陣列將組合分組:

<?xml version="1.0" encoding="utf-8"?>
<restrictions xmlns:android="http://schemas.android.com/apk/res/android" >

  <restriction
    android:key="vpn_configuration_list"
    android:restrictionType="bundle_array">
    <restriction
      android:key="vpn_configuration"
      android:restrictionType="bundle">
      <restriction
        android:key="vpn_server"
        android:restrictionType="string"/>
      <restriction
        android:key="vpn_username"
        android:restrictionType="string"/>
      <restriction
        android:key="vpn_password"
        android:restrictionType="string"/>
    </restriction>
  </restriction>

</restrictions>

android:restrictionType 元素支援的類型 已列於表 1,並記錄在 RestrictionsManagerRestrictionEntry

表 1. 限制項目類型和使用方式。

類型 android:restrictionType 一般用量
TYPE_BOOLEAN "bool" 布林值,true 或 false。
TYPE_STRING "string" 字串值,例如名稱。
TYPE_INTEGER "integer" 值為下列值的整數: MIN_VALUEMAX_VALUE
TYPE_CHOICE "choice" android:entryValues 選取的字串值, 通常會顯示為單選清單
TYPE_MULTI_SELECT "multi-select" android:entryValues 中選取值的字串陣列。 用於呈現複選清單 (內含多個選項) 項目,例如選擇要加入許可清單的特定影視內容。
TYPE_NULL "hidden" 隱藏的限制類型。如果這些資訊 但不應出現在 透過使用者介面向使用者顯示可儲存單一字串值。
TYPE_BUNDLE_ARRAY "bundle_array" 可用來儲存限制陣列 bundles。適用於 Android 6.0 (API 級別 23)。

注意: android:entryValues 機器可讀取,無法 本地化使用 android:entries 提供使用者可理解的可本地化值。 每個項目的 android:entryValues 都必須有對應的索引。

檢查受管理的設定

您的應用程式不會在其他應用程式變更時自動通知 配置設定您必須檢查 就是應用程式開始或繼續運作,並監聽 系統意圖,瞭解設定是否在 應用程式正在執行中。

如要查看目前的配置設定,應用程式會使用 RestrictionsManager 物件。您的應用程式應 在以下時間檢查目前的受管理設定:

如要取得 RestrictionsManager 物件,請取得 getActivity()的活動,之後 呼叫該活動的 Activity.getSystemService() 方法:

Kotlin

var myRestrictionsMgr =
        activity?.getSystemService(Context.RESTRICTIONS_SERVICE) as RestrictionsManager

Java

RestrictionsManager myRestrictionsMgr =
    (RestrictionsManager) getActivity()
        .getSystemService(Context.RESTRICTIONS_SERVICE);

有了 RestrictionsManager,您就能取得 藉由呼叫 getApplicationRestrictions() 方法:

Kotlin

var appRestrictions: Bundle = myRestrictionsMgr.applicationRestrictions

Java

Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

注意:為了方便起見,您也可以擷取目前的 方法是呼叫 UserManager UserManager.getApplicationRestrictions()。這個方法的行為完全符合 與 RestrictionsManager.getApplicationRestrictions() 相同。

getApplicationRestrictions() 方法需要從資料儲存空間讀取資料,因此 應該謹慎處理不要在每次需要時呼叫這個方法 瞭解目前的設定而是應在應用程式執行時呼叫一次 啟動或繼續作業,以及快取擷取的受管理設定套件。然後聆聽 ACTION_APPLICATION_RESTRICTIONS_CHANGED意圖瞭解設定值 變更, 監聽受管理設定變更

讀取及套用受管理的設定

getApplicationRestrictions() 方法會傳回 Bundle 當中包含各個已設定的鍵/值組合 值為 BooleanintStringString[]。安裝 Bundle,您可以查看目前的 套用 Chrome 應用程式的標準 Bundle 方法 這些資料類型,例如 getBoolean()getString()

注意:受管理的設定 Bundle 其中包含一個項目,其中包含一個由 受管理的設定提供者不過,您不得假設 都會顯示在套件中 值。

您的應用程式會根據現行做法採取適當行動 受管理的配置設定舉例來說,如果您的應用程式 指定其是否能透過 Windows 裝置 你就會發現設定設為 false,您必須停用資料下載功能,但 裝置有 Wi-Fi 連線,如以下程式碼範例所示:

Kotlin

val appCanUseCellular: Boolean =
        if (appRestrictions.containsKey("downloadOnCellular")) {
            appRestrictions.getBoolean("downloadOnCellular")
        } else {
            // cellularDefault is a boolean using the restriction's default value
            cellularDefault
        }

if (!appCanUseCellular) {
    // ...turn off app's cellular-download functionality
    // ...show appropriate notices to user
}

Java

boolean appCanUseCellular;

if (appRestrictions.containsKey("downloadOnCellular")) {
    appCanUseCellular = appRestrictions.getBoolean("downloadOnCellular");
} else {
    // cellularDefault is a boolean using the restriction's default value
    appCanUseCellular = cellularDefault;
}

if (!appCanUseCellular) {
    // ...turn off app's cellular-download functionality
    // ...show appropriate notices to user
}

如要套用多個巢狀限制,請參閱 bundle_array 限制項目成為 Parcelable 物件集合 並轉換為 Bundle。在本例中 剖析資料,並用來建構伺服器連線選項的清單:

Kotlin

// VpnConfig is a sample class used store config data, not defined
val vpnConfigs = mutableListOf<VpnConfig>()

val parcelables: Array<out Parcelable>? =
        appRestrictions.getParcelableArray("vpn_configuration_list")

if (parcelables?.isNotEmpty() == true) {
    // iterate parcelables and cast as bundle
    parcelables.map { it as Bundle }.forEach { vpnConfigBundle ->
        // parse bundle data and store in VpnConfig array
        vpnConfigs.add(VpnConfig()
                .setServer(vpnConfigBundle.getString("vpn_server"))
                .setUsername(vpnConfigBundle.getString("vpn_username"))
                .setPassword(vpnConfigBundle.getString("vpn_password")))
    }
}

if (vpnConfigs.isNotEmpty()) {
    // ...choose a VPN configuration or prompt user to select from list
}

Java

// VpnConfig is a sample class used store config data, not defined
List<VpnConfig> vpnConfigs = new ArrayList<>();

Parcelable[] parcelables =
    appRestrictions.getParcelableArray("vpn_configuration_list");

if (parcelables != null && parcelables.length > 0) {
    // iterate parcelables and cast as bundle
    for (int i = 0; i < parcelables.length; i++) {
        Bundle vpnConfigBundle = (Bundle) parcelables[i];
        // parse bundle data and store in VpnConfig array
        vpnConfigs.add(new VpnConfig()
            .setServer(vpnConfigBundle.getString("vpn_server"))
            .setUsername(vpnConfigBundle.getString("vpn_username"))
            .setPassword(vpnConfigBundle.getString("vpn_password")));
    }
}

if (!vpnConfigs.isEmpty()) {
    // ...choose a VPN configuration or prompt user to select from list
}

監聽受管理的設定變更

每當應用程式的受管理設定發生變更,系統就會觸發 ACTION_APPLICATION_RESTRICTIONS_CHANGED 意圖。應用程式必須監聽 這個意圖可讓您在配置設定時變更應用程式的行為 變更。

注意:ACTION_APPLICATION_RESTRICTIONS_CHANGED 意圖只會傳送給事件監聽器 是動態註冊的,而不是宣告的事件監聽器 。

以下程式碼顯示如何動態註冊廣播接收器: 定義:

Kotlin

val restrictionsFilter = IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED)

val restrictionsReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {

        // Get the current configuration bundle
        val appRestrictions = myRestrictionsMgr.applicationRestrictions

        // Check current configuration settings, change your app's UI and
        // functionality as necessary.
    }
}

registerReceiver(restrictionsReceiver, restrictionsFilter)

Java

IntentFilter restrictionsFilter =
    new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);

BroadcastReceiver restrictionsReceiver = new BroadcastReceiver() {
  @Override public void onReceive(Context context, Intent intent) {

    // Get the current configuration bundle
    Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

    // Check current configuration settings, change your app's UI and
    // functionality as necessary.
  }
};

registerReceiver(restrictionsReceiver, restrictionsFilter);

注意:一般情況下,您的應用程式不需收到通知 也會知道哪些設定會在暫停狀態時變更而是應取消註冊 廣播接收器。應用程式重新啟用後, 請先檢查目前的受管理設定 (如 檢查受管理的設定),然後註冊 廣播接收器以確保您收到設定變更的通知 在應用程式啟用期間發生的任何事件

傳送受管理設定的意見回饋給 EMM

將受管理的設定變更套用至應用程式後,最佳做法是通知 EMM 變更狀態Android 支援名為「輸入應用程式狀態」的功能,您可以 會在應用程式每次嘗試套用受管理的設定變更時傳送意見回饋。這個 意見回饋可做為確認應用程式已成功調整受管理的設定,也可以 在應用程式無法套用指定的變更時,則顯示錯誤訊息。

EMM 供應商可以擷取這些意見回饋,並在控制台中顯示,供 IT 人員查看 即可查看。詳情請參閱傳送應用程式意見回饋給 EMM ,包括說明如何在應用程式中加入意見回饋支援服務的詳細指南。

其他程式碼範例

ManagedConfigurations 進一步示範了本頁提到的 API 用法。