Mit dem AMAPI SDK (Android Management API) kann eine von EMMs angegebene Erweiterungs-App direkt mit Android Device Policy (ADP) kommunizieren und Commands
auf dem Gerät ausführen.
Weitere Informationen zu dieser Bibliothek und dazu, wie du sie deiner Anwendung hinzufügen kannst, findest du unter AMAPI SDK einbinden.
Nach der Integration des SDK kann Ihre Erweiterungs-App mit ADP kommunizieren, um:
Befehl ausführen
Eine Erweiterungsanwendung kann anfordern, dass Befehle über ADP erteilt werden.
IssueCommandRequest
enthält das Anfrageobjekt mit Details zum auszugebenden Befehl und spezifischen Parametern.
Im folgenden Snippet wird gezeigt, wie eine Anfrage zum Löschen der Daten des Pakets gesendet wird:
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();
}
...
Im vorherigen Beispiel wird eine Anfrage zum Löschen von App-Daten für bestimmte Pakete gesendet und darauf gewartet, bis der Befehl erfolgreich ausgeführt wurde. Bei Erfolg wird ein Command
-Objekt mit dem aktuellen Befehlsstatus und der Befehls-ID zurückgegeben. Mit dieser ID kann später der Status aller Befehle mit langer Ausführungszeit abgefragt werden.
Befehl abrufen
Eine Erweiterungs-App kann den Status zuvor gesendeter Befehlsanfragen abfragen. Um den Status eines Befehls abzurufen, benötigen Sie die Befehls-ID, die in der Anfrage zum Ausführen des Befehls enthalten ist. Im folgenden Snippet wird gezeigt, 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 Statusänderungen von Befehlen empfangen
Eine Erweiterungs-App kann optional einen Rückruf registrieren, um Updates für Statusänderungen von lang laufenden Befehlen zu erhalten. Gehen Sie dazu so vor:
- Änderungen am Befehlsstatus werden an
CommandListener
gesendet. Implementieren Sie diese Schnittstelle in Ihrer App und geben Sie an, wie mit den empfangenen Statusaktualisierungen umgegangen werden soll. - Erweitern Sie
NotificationReceiverService
und geben Sie über die MethodegetCommandListener
eineCommandListener
-Instanz an. Geben Sie den Klassennamen der 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 public CommandListener getCommandListener() { // return the concrete implementation from previous step return ...; } }
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"
}
}]
Test
Unittest
LocalCommandClient
ist eine Schnittstelle und ermöglicht so eine testbare Implementierung.
Integrationstests
Für den Test mit ADP sind die folgenden Informationen erforderlich:
- Paketname der Erweiterungs-App.
- Der hexadezimal codierte SHA-256-Hash der Signatur, die mit dem App-Paket verknüpft ist.
- Optional, wenn Callback getestet wird: Vollständig qualifizierter Name des Dienstes aus dem neu eingeführten Dienst, der Callback unterstützt. (Vollständig qualifizierter Name von
CommandService
im Beispiel)