Android 利用 Managed Profile 確保兼容性

2018-08-02 18:03 更新

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

Android 平臺允許設(shè)備有 managed profile。managed profile 由管理員控制,它的功能和用戶原本的 profile 的功能是分別設(shè)置的。通過這種方法,在用戶設(shè)備上運行的企業(yè)所定制應(yīng)用程序和數(shù)據(jù)的環(huán)境就在企業(yè)的控制之下,同時用戶還能使用私人的應(yīng)用程序和 profile。

本節(jié)課展示了如何修改你的應(yīng)用程序,使之能夠在有 managed profile 的設(shè)備上可靠運行。除了一般應(yīng)用開發(fā)的最佳實踐外,你不用做任何事。然而,在有 managed profile 的設(shè)備上,最佳實踐的其中一些規(guī)范變得尤為重要。本文件強(qiáng)調(diào)了你所需要了解的問題。

概述

用戶經(jīng)常想在企業(yè)環(huán)境中使用他們的私人設(shè)備。這種情況可能讓企業(yè)陷入困境。如果用戶使用他們的私人設(shè)備,企業(yè)不得不擔(dān)心在這個不受控制的設(shè)備上的機(jī)密信息(例如員工的電子郵件和通訊錄)。

為了處理這種情況,Android 5.0(API 21)允許企業(yè)設(shè)置 managed profile。如果設(shè)備有 managed profile,這個 profile 的設(shè)置是在企業(yè)管理員的控制之下的。管理員可以選擇在這個 profile 之下,什么應(yīng)用程序可以運行,什么設(shè)備功能可以允許。

如果一個設(shè)備有 managed profile,那么,無論應(yīng)用程序在哪個 profile 之下運行,都意味著:

  • 默認(rèn)情況下,大部分的 intent 無法從一個 profile 跨越到另一個。如果在某個 profile 之下的一個應(yīng)用程序創(chuàng)建了 intent,而這個 profile 無法響應(yīng),又因為 profile 的限制這個 intent 不允許跨越到其他 profile,那么,這個請求就失敗了,應(yīng)用程序可能意外關(guān)閉。
  • profile 管理員可以在 managed profile 中限制哪個系統(tǒng)應(yīng)用程序可以運行。這個限制可能導(dǎo)致在 managed profile 中一些常見的 intent 無法處理。
  • 因為 managed profile 和非 managed profile 有各自的存儲區(qū)域,導(dǎo)致文件 URI 在一個 profile 中有效,但在其他 profile 中無效。在一個 profile 中創(chuàng)建的 intent 可能在其他 profile(取決于 profile 設(shè)置)中被響應(yīng),所以在 intent 中放置文件 URI 是不安全的。

防止失敗的 intent

在一個有 managed profile 的設(shè)備上,intent 是否能從一個 profile 跨越到另一個,存在著限制。大多情況下,一個 intent 在哪個 profile 中創(chuàng)建,就在哪個 profile 中響應(yīng)。如果那個 profile 中無法響應(yīng),就算在其他 profile 中可以響應(yīng),這個 intent 也不會被響應(yīng),而且創(chuàng)建這個 intent 的應(yīng)用程序會意外關(guān)閉。

profile 管理員可以選擇哪個 intent 可以從一個 profile 跨越到另一個。因為是由管理員做決定,所以你無法預(yù)先知道哪個 intent 可以跨越邊界。管理員設(shè)置了這個策略,而且可以在任何時候自由更改。

在你的應(yīng)用程序啟動一個 activity 之前,你應(yīng)該驗證這是可行的。你可以調(diào)用 Intent.resolveActivity() 方法來驗證。如果無法處理,方法會返回 null。如果方法返回值非空,那么至少有一個方法可以處理這個 intent,所以創(chuàng)建這個 intent 是安全的。這種情況下,或者是因為在當(dāng)前 profile 中可以響應(yīng),或者是因為 intent 被允許跨越到可以處理的其他 profile 中,intent 可以被處理。(更多關(guān)于響應(yīng) intent 的信息,請查看 Common Intents。)

例如,如果你的應(yīng)用程序需要設(shè)置定時器,就需要檢查是否能響應(yīng) ACTION_SET_TIMER intent。如果應(yīng)用程序無法響應(yīng)這個 intent,就需要采取恰當(dāng)?shù)男袆樱ɡ顼@示一個錯誤信息)。

public void startTimer(String message, int seconds) {

    // Build the "set timer" intent
    Intent timerIntent = new Intent(AlarmClock.ACTION_SET_TIMER)
            .putExtra(AlarmClock.EXTRA_MESSAGE, message)
            .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
            .putExtra(AlarmClock.EXTRA_SKIP_UI, true);

    // Check if there's a handler for the intent
    if (timerIntent.resolveActivity(getPackageManager()) == null) {

        // Can't resolve the intent! Fail this operation cleanly
        // (perhaps by showing an error message)

    } else {
        // Intent resolves, it's safe to fire it off
        startActivity(timerIntent);

    }
}

跨越 profile 共享文件

有時候應(yīng)用程序需要授權(quán)其他運用程序訪問自己的文件。例如,一個圖片庫應(yīng)用可能想與圖片編輯器共享它的圖片。一般共享文件有兩種方法:通過文件 URI 或者內(nèi)容 URI。

一個文件 URI 是由前綴 file: 和文件在設(shè)備中存儲的絕對路徑組成的。然而,因為 managed profile 和私人 profile 有各自的存儲區(qū)域,所以一個文件 URI 在一個 profile 中是有效的,在其他 profile 中是無效的。這種情況意味著,如果你要在 intent 中放置一個文件 URI,而這個 intent 要在其他 profile 中響應(yīng),那么響應(yīng)方是不能訪問這個文件的。

你應(yīng)該取而代之用內(nèi)容 URI 共享文件。內(nèi)容 URI 用一種更安全、更易于分享的方式來識別文件。內(nèi)容 URI 包括了文件路徑,文件提供者,以及文件 ID。你可以通過 FileProvider 為任何文件生成內(nèi)容 ID。然后,你就可以和(甚至在其他 profile 中的)其他應(yīng)用程序共享內(nèi)容 ID。響應(yīng)方可以使用內(nèi)容 ID 來訪問實際文件。

例如,這里展示了你怎么獲得一個指定文件 URI 的內(nèi)容 URI:

// Open File object from its file URI
File fileToShare = new File(fileUriToShare);

Uri contentUriToShare = FileProvider.getUriForFile(getContext(),
        "com.example.myapp.fileprovider", fileToShare);

當(dāng)你調(diào)用 getUriForFile() 方法時,必須包括文件提供者的權(quán)限(在這個例子里是"com.example.myapp.fileprovider"),在應(yīng)用程序的 manifest 中,用 \ 元素設(shè)定這個權(quán)限。更多關(guān)于用內(nèi)容 URI 共享文件的信息,請查看共享文件

在 managed profile 環(huán)境測試你的應(yīng)用程序的兼容性

你要在有 managed profile 的環(huán)境中測試你的應(yīng)用程序,以發(fā)現(xiàn)會引起運行失敗的問題。在一個有 managed profile 的設(shè)備中測試是一個驗證你的應(yīng)用程序正確響應(yīng) intent 的好辦法:無法響應(yīng)的時候不創(chuàng)建 intent,不使用無法跨越 profile 的 URI 等等。

我們提供了一個示例應(yīng)用程序,BasicManagedProfile,你可以用它在一個運行 Android 5.0 或者更高系統(tǒng)的 Android 設(shè)備上設(shè)置一個 managed profile。這個應(yīng)用程序為在有 managed profile 的環(huán)境中來測試你的應(yīng)用程序提供了一個簡單的方法。你也可以按照下面的方法用這個應(yīng)用程序來設(shè)置你的 managed profile:

  • 在 managed profile 中設(shè)定哪些默認(rèn)應(yīng)用程序可以使用
  • 設(shè)定哪些 intent 被允許從一個 profile 跨越到另一個

如果你通過 USB 線手動安裝一個有 managed profile 的應(yīng)用程序,那么在 managed profile 和非 managed profile 之中都安裝有這個應(yīng)用程序。只要你安裝了應(yīng)用程序,你就能在以下條件下進(jìn)行測試:

  • 如果一個 intent 可以被一個默認(rèn)的應(yīng)用程序(例如相機(jī)應(yīng)用程序)響應(yīng),試試 managed profile 中禁用這個默認(rèn)應(yīng)用程序,然后驗證這個應(yīng)用程序可以做出恰當(dāng)?shù)男袨椤?/li>
  • 如果你創(chuàng)建了一個 intent 希望被其他應(yīng)用程序響應(yīng),試試啟用以及禁用這個 intent 從一個 profile 跨越到另一個的權(quán)限。驗證在這兩種情況下應(yīng)用程序都能做出恰當(dāng)?shù)男袨?。如?intent 不允許在 profile 之間跨越,無論當(dāng)前 profile 是否能做出響應(yīng),都要驗證應(yīng)用程序能做出恰當(dāng)?shù)男袨?。例如,如果你的?yīng)用程序創(chuàng)建了一個地圖相關(guān)的 intent,試試以下每一種情況:
    • 設(shè)備允許地圖 intent 從一個 profile 跨越到另一個,并且在另一個(并非應(yīng)用程序所運行的) profile 之中有恰當(dāng)?shù)捻憫?yīng)
    • 設(shè)備不允許地圖 intent 在 profile 之間跨越,但是在應(yīng)該程序所運行的 profile 之中有恰當(dāng)?shù)捻憫?yīng)
    • 設(shè)備不允許地圖 intent 在 profile 之間跨越,并且在設(shè)備的 profile 之中沒有恰當(dāng)?shù)捻憫?yīng)
  • 如果你在 intent 里放置了內(nèi)容,不管是在當(dāng)前 profile 之中,還是在跨越 profile 之后,都要驗證 intent 能有恰當(dāng)?shù)男袨椤?/li>

在 managed profile 環(huán)境測試:提示與技巧

你會發(fā)現(xiàn)在有 managed profile 的設(shè)備里進(jìn)行測試有一些技巧。

  • 如前所述,當(dāng)你側(cè)載一個應(yīng)用程序到一個有 managed profile 的設(shè)備里,是在 managed profile 和非 managed profile 之中都安裝了。如果你愿意,你可以從一個 profile 之中刪除,在另一個 profile 之中留下。
  • 安卓調(diào)試橋(adb)shell 端可用的 activity manager 命令大部分都支持 --user 標(biāo)識,你可以用之設(shè)定運行應(yīng)用程序的用戶。通過設(shè)定一個用戶,你可以選擇是在 managed profile 之中運行,還是在非 managed profile 之中運行。更多信息,請查看 ADB Shell Commands。
  • 為了找到設(shè)備上的活躍用戶,使用 adb 包管理器的 list users 命令。輸出的字符串中第一個數(shù)字是用戶 ID,你可以用于 --user 標(biāo)識。更多信息,請查看 ADB Shell Commands。

例如,為了找到一個設(shè)備上的用戶,你會運行這個命令:

$ adb shell pm list users
UserInfo{0:Drew:13} running
UserInfo{10:Work profile:30} running

在這里,非 managed profile("Drew")有個 ID 為 0 的用戶,而 managed profile 有個 ID 為 10 的用戶。要在工作 profile 之中運行一個應(yīng)用程序,你會用到這樣的命令:

$ adb shell am start --user 10 \
-n "com.example.myapp/com.example.myapp.testactivity" \
-a android.intent.action.MAIN -c android.intent.category.LAUNCHER


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號