Android 實現(xiàn) app 的限制

2018-08-02 18:03 更新

編寫:zenlynn 原文:http://developer.android.com/training/enterprise/app-restrictions.html

如果你為企業(yè)市場開發(fā) app ,你可能需要滿足企業(yè)政策的特殊要求。應(yīng)用程序的限制允許企業(yè)管理員遠程設(shè)定 app 。這種能力對于部署了 managed profile 的企業(yè) app 來說,尤其有用。

例如,一個企業(yè)可能需要核準的 app 允許企業(yè)管理員:

  • 為一個網(wǎng)頁瀏覽器添加白名單或黑名單網(wǎng)址
  • 配置是否允許一個 app 通過蜂窩網(wǎng)絡(luò)同步內(nèi)容,或只能通過 Wi-Fi
  • 配置 app 的電子郵件設(shè)定

這個指南展示了如何在你的 app 實現(xiàn)這個配置設(shè)定。

注意:由于歷史原因,這些配置設(shè)定被稱為限制,并在文件與類中使用這個術(shù)語(例如 RestrictionsManager)。然而,這些限制實際上可以實現(xiàn)各種各樣的配置選項,并不只是限制 app 的功能。

遠程配置概述

app 定義了管理員可以遠程設(shè)定的限制和配置選項。限制提供者可以隨意改變配置設(shè)定。如果你的 app 運行在企業(yè)設(shè)備上的 managed profile 中 ,企業(yè)管理員可以改變該 app 的限制。

限制提供者是運行在同一個設(shè)備上的另一個 app 。這個 app 通常是由企業(yè)管理員控制。企業(yè)管理員向限制提供者 app 傳達限制的改變。這個 app 就相應(yīng)地改變你的 app 的限制。

提供外部可配置的限制:

  • 在你 app 的 manifest 中聲明限制。這么做允許企業(yè)管理員通過 Goodle Play 的接口讀取 app 的限制。
  • 每當 app 恢復,使用 RestrictionsManager 對象檢查當前限制,并改變你的 app 的 UI 和行為以符合這些限制。

定義 app 的限制

你的 app 支持任何你想要定義的限制。你在限制文件中聲明 app 的限制,在 manifest 中聲明限制文件。創(chuàng)建一個限制文件允許其他 app 檢查你的 app 提供的限制。企業(yè)移動管理(EMM)合作者可以通過 Google Play 接口來讀取你的 app 的限制。

為了定義你的 app 的遠程配置選項,把以下元素放在你的 manifest 中的 \ 元素里。

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

在 res/xml 文件夾中創(chuàng)建一個名為 app_restrictions.xml 的文件。該文件的結(jié)構(gòu)在 RestrictionsManager的參考文獻中有所 描述。該文件有一個單獨的頂級的 <restrictions> 元素,這個元素包括一個 <restriction>子元素對應(yīng) app 的每一個配置選項。

注意:不要創(chuàng)建限制文件的地區(qū)化版本。你的 app 只允許有一個限制文件,這樣你的 app 在所有地區(qū)的限制才會保持一致。

在一個企業(yè)環(huán)境中,EMM 一般會使用該限制的框架為 IT 管理員生成遠程控制臺,所以管理員可以遠程配置你的 app 。

例如,假設(shè)你的 app 可以被遠程配置允許或禁止它在蜂窩連接下下載數(shù)據(jù)。你的 app 就會有一個像這樣的 <restriction> 元素:

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

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

</restrictions>

RestrictionsManager 的參考文獻中記載了 android:restrictionType 元素所支持的類型。

注意:Goole Play for Work 不支持 bundle 和 bundle_array 限制類型。

使用每個限制的 android:key 屬性從限制 bundle 中讀取它的值。為此,每個限制必須有一個獨特的 key 字符串,并且不能被地區(qū)化。它必須用一個 string 直接量指明。

注意:如在資源地區(qū)化所說,在一個產(chǎn)品 app 中,android:title 和 android:description 應(yīng)該從地區(qū)化資源文件中提取出來。

限制提供者可以詢問 app 來找到該 app 可用限制的細節(jié),包括它們的描述文本。限制提供者和企業(yè)管理員可以在任何時候,甚至 app 沒有在運行的時候,改變它的限制。

檢查 app 的限制

當其他 app 改變你的 app 的限制設(shè)定時,你的 app 不會被自動通知。反而需要你在 app 啟動或恢復的時候檢查有哪些限制,并且監(jiān)聽系統(tǒng) intent 來發(fā)現(xiàn)當你的 app 運行的時候限制是否發(fā)生改變。

為了知道當前限制設(shè)定,你的 app 使用一個 RestrictionsManager 對象。你的 app 應(yīng)該在以下時候檢查當前限制:

  • 當 app 啟動或者恢復的時候,在它的 onResume() 方法里檢查

為了獲得一個 RestrictionsManager 對象,使用 getActivity() 取得當前 activity,然后調(diào)用 activity 的 Activity.getSystemService() 方法:

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

一旦你有了 RestrictionsManager,你可以通過調(diào)用它的 getApplicationRestrictions() 方法取得當前的限制設(shè)定:

Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

注意:方便起見,你也可以用 UserManager 取得當前限制,調(diào)用 UserManager.getApplicationRestrictions() 即可。這個方法與 RestrictionsManager.getApplicationRestrictions() 起到完全相同的作用。

getApplicationRestrictions() 方法需要從數(shù)據(jù)存儲區(qū)獲得數(shù)據(jù),所以要盡量少用。不要每次你需要知道當前限制的時候就調(diào)用這個方法。你應(yīng)該只在你的 app 啟動或恢復的時候調(diào)用,并且緩存所取得的限制 bundle。然后,如監(jiān)聽 app 配置的改變中所說,在你的 app 活動的時候,監(jiān)聽 ACTION_APPLICATION_RESTRICTIONS_CHANGED intent 來發(fā)現(xiàn)限制是否改變。

當你的 app 使用 RestrictionsManager.getApplicationRestrictions() 檢查限制時,我們建議你檢查企業(yè)管理員是否把鍵值對 KEY_RESTRICTIONS_PENDING 設(shè)置為 true。如果設(shè)置了,你應(yīng)該阻止用戶使用這個 app,并提示他們聯(lián)系他們的企業(yè)管理員。然后,這個 app 應(yīng)該繼續(xù)正常運行,注冊 ACTION_APPLICATION_RESTRICTIONS_CHANGED 廣播。

Figure 1. 在注冊廣播之前檢查限制是否暫掛

讀取并應(yīng)用限制

getApplicationRestrictions() 方法返回一個 Bundle,其中包含了被設(shè)置的每個限制的鍵值對。這些值的類型是 BooleanintStringString[]BundleBundle[]。只要你有了限制 Bundle ,你就可以用標準的 Bundle 方法針對數(shù)據(jù)類型來檢查當前的限制設(shè)置,比如 getBoolean() 或者 getString()。

注意:限制 Bundle 為每個被限制提供者顯式設(shè)置的限制都包括了一個條目。但是,你不能只因為你在限制 XML 文件中定義了一個默認值,就假定這個限制就會在 bundle 里出現(xiàn)。

你基于當前的限制設(shè)定,為你的 app 采取合適的行動。比如,如果你的 app 有一個限制架構(gòu)來指明是否它能在蜂窩連接(就像在定義 app的 限制的例子里一樣)中下載,而你發(fā)現(xiàn)限制設(shè)置為 false,那么你不得不禁止數(shù)據(jù)下載,除非設(shè)備在 Wi-Fi 連接下,正如下面的實例代碼所展示的:

boolean appCanUseCellular;

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

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

注意:該限制架構(gòu)必須向前向后兼容,因為 Google Play for Work 對于每個 app 只給予 EMM 一個版本的限制架構(gòu)。

監(jiān)聽 app 限制的改變

每當 app 的限制被改變,系統(tǒng)就創(chuàng)建 ACTION_APPLICATION_RESTRICTIONS_CHANGED intent。你的 app 必須監(jiān)聽這個 intent,這樣你就能在限制設(shè)定改變的時候改變 app 的行為。

注意:ACTION_APPLICATION_RESTRICTIONS_CHANGED intent 只發(fā)送給動態(tài)注冊的監(jiān)聽者,而不發(fā)送給在 app manifest 里聲明的監(jiān)聽者。

以下代碼展示了如何為這個 intent 動態(tài)注冊一個廣播接收者:

IntentFilter restrictionsFilter =
    new IntentFilter(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);

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

    // Get the current restrictions bundle
    Bundle appRestrictions =

    myRestrictionsMgr.getApplicationRestrictions();

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

  }

};

registerReceiver(restrictionsReceiver, restrictionsFilter);

注意:一般來說,當你的 app 中止時不需要被通知限制的改變。相反,這個時候你需要注銷你的廣播接收者。當 app 恢復時,你首先要檢查當前的限制(正如在檢查 app 的限制中所討論的),然后注冊你的廣播接收者,以保證在 app 活動期間如果有限制改變你會被通知。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號