Ustawianie konfiguracji zarządzanych

Jeśli opracowujesz aplikacje na rynek korporacyjny, może być konieczne spełnienie określonych wymagań określonych w zasadach organizacji. Konfiguracje zarządzane, wcześniej znane jako ograniczenia aplikacji, umożliwiają administratorowi IT organizacji zdalne określanie ustawień aplikacji. Ta funkcja jest szczególnie przydatna w przypadku aplikacji zatwierdzonych przez organizację i wdrożonych na profilu służbowym.

Organizacja może na przykład wymagać, aby zatwierdzone aplikacje umożliwiały administratorowi IT:

  • Zezwalanie na adresy URL w przeglądarce i ich blokowanie
  • Określ, czy aplikacja ma mieć możliwość synchronizowania treści przez sieć komórkową, czy tylko przez Wi-Fi.
  • Konfigurowanie ustawień poczty e-mail aplikacji

Ten przewodnik pokazuje, jak wdrożyć ustawienia konfiguracji zarządzanej w aplikacji. Aby wyświetlić przykładowe aplikacje z konfiguracją zarządzaną, zapoznaj się z artykułem ManagedConfigurations. Jeśli jesteś deweloperem usług zarządzania urządzeniami mobilnymi (EMM), zapoznaj się z przewodnikiem po interfejsie Android Management API.

Uwaga: z historycznych powodów te ustawienia konfiguracji są nazywane ograniczeniami i są implementowane za pomocą plików i klas, które używają tego terminu (np. RestrictionsManager). Te ograniczenia mogą jednak implementować szeroki zakres opcji konfiguracji, a nie tylko ograniczenia funkcjonalności aplikacji.

Omówienie zdalnej konfiguracji

Aplikacje określają opcje konfiguracji zarządzanej, które mogą być ustawiane zdalnie przez administratora IT. Są to dowolne ustawienia, które mogą być zmieniane przez dostawcę konfiguracji zarządzanej. Jeśli aplikacja działa w profilu służbowym, administrator IT może zmienić jej konfigurację zarządzaną.

Dostawca konfiguracji zarządzanych to inna aplikacja działająca na tym samym urządzeniu. Zazwyczaj tą aplikacją zarządza administrator IT. Administrator IT przekazuje zmiany konfiguracji aplikacji zarządzanej aplikacji dostawcy konfiguracji. Ta aplikacja z kolei zmienia konfiguracje w Twojej aplikacji.

Aby udostępnić konfiguracje zarządzane z zewnątrz:

  • Zadeklaruj konfiguracje zarządzane w manifeście aplikacji. Pozwoli to administratorowi IT odczytywać konfiguracje aplikacji za pomocą interfejsów Google Play API.
  • Gdy aplikacja zostanie wznowiona, użyj obiektu RestrictionsManager, aby sprawdzić bieżące konfiguracje zarządzane, a następnie zmień interfejs i zachowanie aplikacji, aby dostosować je do tych konfiguracji.
  • Nasłuchuj intencję ACTION_APPLICATION_RESTRICTIONS_CHANGED. Gdy otrzymasz tę wiadomość, sprawdź RestrictionsManager, aby dowiedzieć się, jakie są aktualne konfiguracje zarządzane, i wprowadź w swojej aplikacji niezbędne zmiany.

Definiowanie konfiguracji zarządzanych

Aplikacja może obsługiwać dowolną konfigurację zarządzaną, którą chcesz zdefiniować. Konfiguracje zarządzane aplikacji deklarujesz w pliku konfiguracji zarządzanej, a plik konfiguracji w pliku manifestu. Utworzenie pliku konfiguracji umożliwia innym aplikacjom sprawdzanie konfiguracji zarządzanej udostępnianej przez Twoją aplikację. Partnerzy EMM mogą odczytywać konfiguracje aplikacji za pomocą interfejsów Google Play API.

Aby zdefiniować opcje zdalnej konfiguracji aplikacji, umieść w pliku manifestu element <application>:

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

Utwórz w katalogu res/xml aplikacji plik o nazwie app_restrictions.xml. Struktura tego pliku jest opisana w dokumentacji dotyczącej pliku RestrictionsManager. Plik zawiera: 1 element najwyższego poziomu <restrictions>, który zawiera 1 element podrzędny <restriction> dla każdej opcji konfiguracji aplikacji.

Uwaga: nie twórz zlokalizowanych wersji pliku konfiguracji zarządzanej. Aplikacja może mieć tylko 1 plik konfiguracji zarządzanej, aby konfiguracje były spójne w przypadku wszystkich lokalizacji aplikacji.

W środowisku korporacyjnym system EMM zwykle używa schematu konfiguracji zarządzanej do generowania konsoli zdalnej dla administratorów IT, aby mogli zdalnie konfigurować aplikację.

Dostawca skonfigurowanych konfiguracji może wysłać zapytanie do aplikacji, aby uzyskać szczegółowe informacje o dostępnych konfiguracjach aplikacji, w tym ich opisy. Dostawca konfiguracji i administrator IT mogą w każdej chwili zmienić konfiguracje zarządzane aplikacji, nawet gdy aplikacja nie jest uruchomiona.

Załóżmy na przykład, że aplikacja może być konfigurowana zdalnie, aby zezwalać lub zabraniać pobierania danych przez połączenie komórkowe. Aplikacja może zawierać element <restriction>, który wygląda tak:

<?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>

Używasz atrybutu android:key każdej konfiguracji, aby odczytać jego wartość z pakietu konfiguracji zarządzanej. Z tego powodu każda konfiguracja musi mieć unikalny ciąg znaków klucza, który nie może zostać zlokalizowany. Musisz go podać jako ciąg znaków.

Uwaga: w wersji produkcyjnej aplikacji zmienne android:titleandroid:description powinny być pobierane z zlokalizowanego pliku zasobu zgodnie z opisem w artykule Lokalizacja za pomocą zasobów.

Aplikacja określa ograniczenia za pomocą pakietów w ramach bundle_array. Na przykład aplikacja z wieloma opcjami połączenia VPN może zdefiniować konfigurację każdego serwera VPN w elementach bundle, a kilka pakietów może być zgrupowanych w tablicy pakietów:

<?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>

Obsługiwane typy elementu android:restrictionType wymieniono w tabeli 1 i opisano w dokumentacji elementów RestrictionsManager i RestrictionEntry.

Tabela 1. Typy i zastosowanie wpisów z ograniczeniami.

Typ android:restrictionType Typowe zastosowanie
TYPE_BOOLEAN "bool" Wartość logiczna (prawda lub fałsz).
TYPE_STRING "string" Wartość ciągu, np. nazwa.
TYPE_INTEGER "integer" Liczba całkowita z zakresu MIN_VALUEMAX_VALUE.
TYPE_CHOICE "choice" Wartość ciągu znaków wybrana z android:entryValues, zwykle jako lista rozwijana.
TYPE_MULTI_SELECT "multi-select" Tablica ciągów znaków z wartościami wybranymi z android:entryValues. Użyj tego, aby wyświetlić listę wielokrotnego wyboru, na której można zaznaczyć więcej niż 1 pozycję, np. aby wybrać konkretne tytuły do dodania do listy dozwolonych.
TYPE_NULL "hidden" Ukryty typ ograniczenia. Używaj tego typu w przypadku informacji, które muszą być przenoszone, ale nie powinny być wyświetlane użytkownikowi w interfejsie. przechowuje pojedynczą wartość ciągu znaków;
TYPE_BUNDLE_ARRAY "bundle_array" Używaj tego do przechowywania tablic ograniczeń bundles. Dostępne w Androidzie 6.0 (poziom interfejsu API 23).

Uwaga: android:entryValues są czytelne dla maszyn i nie można ich przetłumaczyć. Użyj android:entries, aby przedstawić wartości czytelne dla człowieka, które można zlokalizować. Każdy wpis musi mieć odpowiedni indeks w elementach android:entryValues.

Sprawdzanie konfiguracji zarządzanych

Aplikacja nie jest automatycznie powiadamiana, gdy inne aplikacje zmieniają jej ustawienia konfiguracji. Zamiast tego sprawdź, jakie są konfiguracje zarządzane podczas uruchamiania lub wznawiania aplikacji i słuchaj intencji systemu, aby dowiedzieć się, czy konfiguracje zmieniają się podczas działania aplikacji.

Aby sprawdzić bieżące ustawienia konfiguracji, aplikacja używa obiektu RestrictionsManager. Aplikacja powinna sprawdzać aktualne konfiguracje zarządzane w tych momentach:

Aby uzyskać obiekt RestrictionsManager, pobierz bieżącą aktywność za pomocą metody getActivity(), a następnie wywołaj metodę Activity.getSystemService() tej aktywności:

Kotlin

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

Java

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

Po utworzeniu obiektu RestrictionsManager możesz uzyskać bieżące ustawienia konfiguracji, wywołując metodę getApplicationRestrictions():

Kotlin

var appRestrictions: Bundle = myRestrictionsMgr.applicationRestrictions

Java

Bundle appRestrictions = myRestrictionsMgr.getApplicationRestrictions();

Uwaga: dla wygody możesz też pobrać bieżące konfiguracje za pomocą UserManager, wywołując funkcję UserManager.getApplicationRestrictions(). Ta metoda działa dokładnie tak samo jak RestrictionsManager.getApplicationRestrictions().

Metoda getApplicationRestrictions() wymaga odczytu z magazynu danych, dlatego należy stosować ją oszczędnie. Nie wywołuj tej metody za każdym razem, gdy chcesz poznać bieżącą konfigurację. Zamiast tego wywołaj go raz, gdy aplikacja się uruchamia lub wznawia działanie, i zapisz w pamięci podręcznej pobrany pakiet konfiguracji zarządzanych. Następnie nasłuchuj intencję ACTION_APPLICATION_RESTRICTIONS_CHANGED, aby dowiedzieć się, czy konfiguracja zmieniła się, gdy aplikacja była aktywna, zgodnie z opisem w artykule Nasłuchiwanie zmian w konfiguracji zarządzanej.

Czytanie i stosowanie konfiguracji zarządzanych

Metoda getApplicationRestrictions() zwraca obiekt Bundle zawierający parę klucz-wartość dla każdej skonfigurowanej konfiguracji. Wszystkie wartości są typu Boolean, int, String lub String[]. Po utworzeniu konfiguracji zarządzanej Bundle możesz sprawdzić bieżące ustawienia konfiguracji za pomocą standardowych metod Bundle dla tych typów danych, takich jak getBoolean() lub getString().

Uwaga: sekcja Konfiguracje zarządzane Bundle zawiera 1 element dla każdej konfiguracji, która została wyraźnie ustawiona przez dostawcę konfiguracji zarządzanych. Nie można jednak zakładać, że konfiguracja będzie obecna w pakiecie tylko dlatego, że zdefiniowano domyślną wartość w pliku XML z konfiguracjami zarządzanymi.

Aplikacja musi podjąć odpowiednie działanie na podstawie bieżących ustawień konfiguracji zarządzanej. Jeśli na przykład aplikacja ma konfigurację określającą, czy może pobierać dane przez połączenie komórkowe, i okaże się, że konfiguracja jest ustawiona na false, musisz wyłączyć pobieranie danych, z wyjątkiem sytuacji, gdy urządzenie ma połączenie Wi-Fi, jak pokazano w tym przykładowym kodzie:

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
}

Aby zastosować wiele zagnieżdżonych ograniczeń, odczytaj wpis ograniczenia bundle_array jako zbiór obiektów Parcelable i przekształc go w wartość typu Bundle. W tym przykładzie dane konfiguracji każdej sieci VPN są analizowane i używane do utworzenia listy opcji połączenia z serwerem:

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
}

Nasłuchiwanie zmian w konfiguracji zarządzanej

Gdy zmienią się zarządzane konfiguracje aplikacji, system uruchamia działanie intencji ACTION_APPLICATION_RESTRICTIONS_CHANGED. Aplikacja musi nasłuchiwać tego zamiaru, aby można było zmienić jej działanie po zmianie ustawień konfiguracji.

Uwaga: intencja ACTION_APPLICATION_RESTRICTIONS_CHANGED jest wysyłana tylko do odbiorców zarejestrowanych dynamicznie, a nie do odbiorców zadeklarowanych w manifeście aplikacji.

Poniższy kod pokazuje, jak dynamicznie zarejestrować odbiornik transmisji dla tej intencji:

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

Uwaga: gdy aplikacja jest wstrzymana, zwykle nie musi otrzymywać powiadomień o zmianach konfiguracji. Zamiast tego, gdy aplikacja jest wstrzymana, powinnaś/powinieneś zarejestrować odbiornik transmisji. Gdy aplikacja zostanie wznowiona, najpierw sprawdź bieżące konfiguracje zarządzane (jak opisano w artykule Sprawdzanie konfiguracji zarządzanych), a potem zarejestruj odbiornik transmisji, aby otrzymywać powiadomienia o zmianach konfiguracji, które mają miejsce, gdy aplikacja jest aktywna.

Wysyłanie opinii na temat konfiguracji zarządzanej do systemów EMM

Po zastosowaniu zmian w zarządzanej konfiguracji aplikacji zalecamy poinformowanie dostawców usług EMM o stanie zmian. Android obsługuje funkcję stany aplikacji z kluczem, która umożliwia wysyłanie opinii za każdym razem, gdy aplikacja próbuje zastosować zmiany w konfiguracji zarządzanej. Te informacje mogą służyć jako potwierdzenie, że aplikacja prawidłowo skonfigurowała ustawienia zarządzane, lub zawierać komunikat o błędzie, jeśli aplikacja nie mogła zastosować określonych zmian.

Dostawcy usług EMM mogą pobierać te opinie i wyświetlać je w swoich konsolach, aby administratorzy IT mogli je przeglądać. Więcej informacji na ten temat, w tym szczegółowy przewodnik po dodawaniu obsługi opinii do aplikacji, znajdziesz w artykule Przesyłanie opinii o aplikacji do EMM.

Dodatkowe przykłady kodu

Przykład ManagedConfigurations pokazuje dodatkowe zastosowania interfejsów API opisanych na tej stronie.

Dodawanie aplikacji do listy dozwolonych lub zablokowanych na profilu osobistym

Sklepy z aplikacjami innych firm mogą wyrazić zainteresowanie korzystaniem z zarządzanych konfiguracji, aby mieć niezawodne sposoby stosowania list zablokowanych i dozwolonych aplikacji zarówno na profilu osobistym, jak i w ramach funkcji Przestrzeń prywatnych, która jest dodatkową przestrzenią osobistą dla użytkowników, w której mogą przechowywać poufne aplikacje. Jeśli tworzysz sklep z aplikacjami na potrzeby przedsiębiorstw i chcesz korzystać z tej funkcji, prześlij ten formularz, aby wyrazić zainteresowanie, a w polu Powód odpowiedzi wybierz Zainteresowanie dodaniem do listy dozwolonych sklepów z aplikacjami.