App di estensioni e comandi locali

L'SDK Android Management API (AMAPI) consente a un'app di estensione specificata da EMM di comunicare direttamente con Android Device Policy (ADP) ed eseguire Commands sul dispositivo.

Eseguire l'integrazione con l'SDK AMAPI fornisce ulteriori informazioni su questa libreria e su come aggiungerla alla tua applicazione.

Una volta integrato l'SDK, l'app di estensione può comunicare con ADP per:

Esegui comando

Un'app di estensione può richiedere l'emissione di comandi utilizzando ADP. IssueCommandRequest contiene l'oggetto request che conterrà i dettagli sul comando da emettere e parametri specifici.

Lo snippet seguente mostra come inviare una richiesta per cancellare i dati del pacchetto:

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

L'esempio precedente mostra l'emissione di una richiesta chiara di dati dell'app per pacchetti specificati e l'attesa dell'emissione del comando. Se il comando viene emesso correttamente, viene restituito un oggetto Command con lo stato corrente del comando e l'ID comando, che può essere utilizzato in un secondo momento per eseguire query sullo stato di eventuali comandi a lunga esecuzione.

Ottieni comando

Un'app di estensione può eseguire query sullo stato delle richieste di comando emesse in precedenza. Per recuperare lo stato di un comando, devi disporre dell'ID comando (disponibile dalla richiesta di esecuzione del comando). Il seguente snippet mostra come inviare un messaggio GetCommandRequest ad 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());
  }
  ...

Ascoltare i callback di modifica dello stato del comando

Facoltativamente, un'app di estensione può registrare un callback per ricevere aggiornamenti per le modifiche dello stato dei comandi a lungo termine seguendo questi passaggi:

  1. Le modifiche allo stato dei comandi vengono comunicate a CommandListener, implementa questa interface nella tua app e fornisci l'implementazione su come gestire gli aggiornamenti dello stato ricevuti.
  2. Estendi NotificationReceiverService e fornisci un'istanza CommandListener tramite il metodo getCommandListener.
  3. Specifica il nome della classe di NotificationReceiverService esteso nel criterio dell'API Android Management (vedi Configurazione dei criteri).

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

Configurazione dei criteri

Per consentire all'app di estensione di comunicare direttamente con ADP, il provider EMM deve fornire un criterio extensionConfig.

 "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

Test delle unità

LocalCommandClient è un'interfaccia e pertanto consente di fornire un'implementazione testabile.

Test di integrazione

Per eseguire il test con ADP saranno necessarie le seguenti informazioni:

  1. Nome del pacchetto dell'app di estensione.
  2. L'hash SHA-256 esadecimale codificato della firma associata al pacchetto dell'app.
  3. Se vuoi testare il callback, facoltativo, il nome completo del servizio dal servizio appena introdotto che supporta il callback. (nome completo di CommandService nell'esempio).