Erweiterungs-Apps und lokale Befehle

Das Android Management API (AMAPI) SDK ermöglicht einer EMM-spezifischen Erweiterungs-App, direkt mit Android Device Policy (ADP) zu kommunizieren und Commands auf dem Gerät auszuführen.

Unter AMAPI SDK einbinden finden Sie weitere Informationen zu dieser Bibliothek und dazu, wie Sie sie Ihrer Anwendung hinzufügen.

Nach der Integration des SDK kann Ihre Erweiterungs-App mit ADP kommunizieren, um:

Ausgabebefehl

Eine Erweiterungs-App kann Befehle anfordern, die über ADP ausgegeben werden. IssueCommandRequest enthält das Anfrageobjekt mit Details zum auszugebenden Befehl und spezifischen Parametern.

Das folgende Snippet zeigt, wie Sie eine Anfrage zum Löschen der Paketdaten senden:

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();
  }
...

Das vorherige Beispiel zeigt, wie eine klare App-Datenanfrage für bestimmte Pakete gesendet wird und gewartet wird, bis der Befehl erfolgreich ausgegeben wurde. Bei erfolgreicher Ausführung wird ein Command-Objekt mit dem aktuellen Befehlsstatus und der Befehls-ID zurückgegeben, mit der später der Status von lang andauernden Befehlen abgefragt werden kann.

Befehl abrufen

Eine Erweiterungs-App kann den Status zuvor gesendeter Befehlsanfragen abfragen. Zum Abrufen des Status eines Befehls benötigen Sie die Befehls-ID. Diese ist in der Ausgabebefehlsanfrage verfügbar. Das folgende Snippet zeigt, wie ein GetCommandRequest an ADP gesendet wird.

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());
  }
  ...

Callbacks für Änderung des Befehlsstatus beobachten

Eine Erweiterungs-App kann einen Callback registrieren, um Updates für Statusänderungen von lang andauernden Befehlen zu erhalten. Dazu gehen Sie so vor:

  1. Änderungen des Befehlsstatus werden an CommandListener informiert. Implementieren Sie diese Schnittstelle in Ihrer App und geben Sie an, wie die empfangenen Statusaktualisierungen verarbeitet werden sollen.
  2. Erweitern Sie NotificationReceiverService und stellen Sie die Instanz CommandListener bereit.
  3. Geben Sie den Klassennamen des erweiterten NotificationReceiverService in der Android Management API-Richtlinie an (siehe Richtlinienkonfiguration).

    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. Fügen Sie den Dienst Ihrer AndroidManifest.xml hinzu und achten Sie darauf, dass er exportiert wurde.

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

Richtlinienkonfiguration

Damit die Erweiterungs-App direkt mit ADP kommunizieren kann, muss der EMM eine extensionConfig-Richtlinie bereitstellen.

 "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"
   }
 }]

Testen

Unittest

LocalCommandClient ist eine Schnittstelle und ermöglicht somit das Bereitstellen einer testbaren Implementierung.

Integrationstests

Für Tests mit ADP sind folgende Informationen erforderlich:

  1. Paketname der Erweiterungs-App.
  2. Der hex-codierte SHA-256-Hash der Signatur, die mit dem Anwendungspaket verknüpft ist.
  3. Optional beim Testen des Callbacks der vollständig qualifizierte Name des Dienstes des neu eingeführten Dienstes zur Unterstützung des Callbacks. (Voll qualifizierter Name von CommandService im Beispiel).