Integracja z pakietem SDK API

Pakiet AMAPI SDK umożliwia aplikacji rozszerzenia określonej przez EMM komunikację bezpośrednio z Android Device Policy. Obecnie obsługuje ono lokalne wykonywanie Commands i tylko polecenie ClearAppData. Aby zintegrować pakiet z pakietem SDK:

  1. Dodaj bibliotekę do rozszerzenia.
  2. W razie potrzeby używaj dostępnych interfejsów API do wydawania poleceń.
  3. Dodaj element zapytania, jeśli docelowy pakiet SDK wynosi >= 30.
  4. Opcjonalnie możesz udostępnić implementację usługi do nasłuchiwania wywołań zwrotnych zmiany stanu polecenia.
  5. Udostępnij urządzenie z zasadą rozszerzania.

Wymagania wstępne

  • Sprawdź, czy parametr minSdkVersion aplikacji rozszerzenia ma ustawiony co najmniej poziom API 21.

Dodawanie biblioteki do rozszerzenia aplikacji

W pliku build.gradle najwyższego poziomu do odpowiednich modułów dodaj repozytorium Google Maven, które zawiera bibliotekę SDK, i dodaj zależność do biblioteki:

repositories {
  ...
  google()
}

Następnie dodaj tę bibliotekę do bloku zależności modułu:

dependencies {
  implementation 'com.google.android.libraries.enterprise.amapi:amapi:1.0.0'
}

Wysyłanie żądań do Android Device Policy

Teraz powinno być możliwe wysyłanie żądań do ADP. Obsługiwane są żądania.

Polecenie wydania

Aplikacja z rozszerzeniem może prosić o wydanie poleceń za pomocą ADP. IssueCommandRequest zawiera obiekt żądania zawierający szczegóły polecenia, które ma zostać wysłane, oraz określone parametry. Więcej informacji na ten temat można znaleźć w dokumencie Javadoc.

Ten fragment kodu pokazuje, jak przesłać prośbę o usunięcie danych pakietu:

import android.util.Log;
...
import com.google.android.managementapi.commands.LocalCommandClientFactory
import com.google.android.managementapi.commands.model.Command
import com.google.android.managementapi.commands.model.GetCommandRequest
import com.google.android.managementapi.commands.model.IssueCommandRequest
import com.google.android.managementapi.commands.model.IssueCommandRequest.ClearAppsData
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;

...
  void issueClearAppDataCommand(ImmutableList<String> packageNames) {
    Futures.addCallback(
        LocalCommandClientFactory.create(getContext())
            .issueCommand(createClearAppRequest(packageNames)),
        new FutureCallback<Command>() {
          @Override
          public void onSuccess(Command result) {
            // Process the returned command result here
            Log.i(TAG, "Successfully issued command");
          }

          @Override
          public void onFailure(Throwable t) {
            Log.e(TAG, "Failed to issue command", t);
          }
        },
        MoreExecutors.directExecutor());
  }

  IssueCommandRequest createClearAppRequest(ImmutableList<String> packageNames) {
    return IssueCommandRequest.builder()
        .setClearAppsData(
            ClearAppsData.builder()
                .setPackageNames(packageNames)
                .build()
        )
        .build();
  }
...

Powyższy przykład przedstawia wysyłanie żądania oczywistych danych aplikacji dotyczących określonych pakietów i oczekiwanie na pomyślne wykonanie polecenia. Jeśli się to stanie, zostanie zwrócony obiekt Command z bieżącym stanem polecenia i identyfikatorem polecenia, którego można później używać do wysyłania zapytań dotyczących stanu dowolnych długo działających poleceń.

Pobierz polecenie

Aplikacja rozszerzenia może też odpytywać o stan poprzednio wysłanych żądań poleceń. Aby pobrać stan polecenia, potrzebujesz jego identyfikatora (dostępnego w żądaniu wydania polecenia). Poniższy fragment pokazuje, jak wysłać żądanie GetCommand do ADP.

import android.util.Log;
...
import com.google.android.managementapi.commands.LocalCommandClientFactory;
...
import com.google.android.managementapi.commands.model.GetCommandRequest;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.MoreExecutors;

...
  void getCommand(String commandId) {
    Futures.addCallback(
        LocalCommandClientFactory.create(getApplication())
            .getCommand(GetCommandRequest.builder().setCommandId(commandId).build()),
        new FutureCallback<Command>() {
          @Override
          public void onSuccess(Command result) {
            // Process the returned command result here
            Log.i(Constants.TAG, "Successfully issued command");
          }

          @Override
          public void onFailure(Throwable t) {
            Log.e(Constants.TAG, "Failed to issue command", t);
          }
        },
        MoreExecutors.directExecutor());
  }
  ...

Dodawanie elementu zapytań

Jeśli Twoja aplikacja jest kierowana na pakiet SDK 30 lub nowszy, wymagany jest element zapytania w pliku manifestu, który wskazuje, że będzie ona wchodzić w interakcje z ADP.

<queries>
    <package android:name="com.google.android.apps.work.clouddpc" />
</queries>

Więcej informacji znajdziesz w artykule Filtrowanie widoczności pakietów na urządzeniach z Androidem .

Nasłuchiwanie wywołań zwrotnych dotyczących zmiany stanu polecenia

  1. Zmiany stanu poleceń są powiadamiane do CommandListener, implementują ten interfejs w aplikacji i zapewniają implementację sposobu obsługi otrzymanych aktualizacji stanu.
  2. Rozszerz usługę NotificationOdbieranierService i udostępnij instancję CommandListener.
  3. Określ nazwę klasy rozszerzonej usługi NotificationpickuprService w zasadach interfejsu Android Management API (zobacz Konfiguracja zasad).

    import com.google.android.managementapi.commands.CommandListener;
    import com.google.android.managementapi.notification.NotificationReceiverService;
    
    ...
    
    public class SampleCommandService extends NotificationReceiverService {
    
      @Override
      protected void setupInjection() {
        // (Optional) If using DI and needs initialisation then use this method.
      }
    
      @Override
      public CommandListener getCommandListener() {
        // return the concrete implementation from previous step
        return ...;
      }
    }
    
  4. Dodaj usługę do pliku AndroidManifest.xml i upewnij się, że została wyeksportowana.

    <service
     android:name = ".notification.SampleCommandService"
     android:exported = "true" />
    

Konfiguracja zasady

 "applications": [{
   "packageName": "com.amapi.extensibility.demo",
   ...
   "extensionConfig": {
     "signingKeyFingerprintsSha256": [
       // Include signing key of extension app
     ],
     // Optional if callback is implemented
     "notificationReceiver": "com.amapi.extensibility.demo.notification.SampleCommandService"
   }
 }]

Testowanie

Testowanie jednostkowe

LocalCommandClient to interfejs, dzięki czemu testowanie umożliwia łatwą implementację testowanej implementacji.

Testowanie integracji

Do testowania przy użyciu Android Device Policy będą potrzebne te informacje:

  1. Nazwa pakietu aplikacji rozszerzenia.
  2. Zaszyfrowany szesnastkowo identyfikator SHA-256 podpisu powiązanego z pakietem aplikacji.
  3. Opcjonalnie w przypadku testowania wywołania zwrotnego – w pełni kwalifikowana nazwa usługi z nowo wprowadzonej usługi do obsługi wywołania zwrotnego. (w tym przykładzie pełna i jednoznaczna nazwa usługi CommandService).