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

2018-08-02 18:03 更新

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

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

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

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

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

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

遠(yuǎn)程配置概述

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

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

提供外部可配置的限制:

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

定義 app 的限制

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

為了定義你的 app 的遠(yuǎn)程配置選項(xiàng),把以下元素放在你的 manifest 中的 \ 元素里。

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

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

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

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

例如,假設(shè)你的 app 可以被遠(yuǎn)程配置允許或禁止它在蜂窩連接下下載數(shù)據(jù)。你的 app 就會(huì)有一個(gè)像這樣的 <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 的參考文獻(xiàn)中記載了 android:restrictionType 元素所支持的類型。

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

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

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

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

檢查 app 的限制

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

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

  • 當(dāng) app 啟動(dòng)或者恢復(fù)的時(shí)候,在它的 onResume() 方法里檢查

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

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

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

Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

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

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

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

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

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

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

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

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

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)必須向前向后兼容,因?yàn)?Google Play for Work 對(duì)于每個(gè) app 只給予 EMM 一個(gè)版本的限制架構(gòu)。

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

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

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

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

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);

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


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)