App di estensioni e comandi locali

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

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 dell'estensione può comunicare con ADP per:

Comando dei problemi

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

Il seguente snippet mostra come inviare una richiesta di cancellazione dei 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'invio di una richiesta di dati dell'app chiara per i pacchetti specificati e l'attesa dell'emissione del comando. Se viene emesso correttamente, verrà restituito un oggetto Command con lo stato del comando attuale e l'ID del comando, che in seguito potrà essere utilizzato per eseguire query sullo stato di qualsiasi comando 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, avrai bisogno dell'ID comando (disponibile nella richiesta del comando issue). Il seguente snippet mostra come inviare un elemento 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());
  }
  ...

Ascolta i callback di modifica dello stato del comando

Un'app di estensione può registrare un callback per ricevere aggiornamenti in caso di modifiche di stato dei comandi a lunga esecuzione seguendo questa procedura:

  1. Le modifiche allo stato del comando vengono notificate a CommandListener, implementa questa interfaccia nella tua app e fornisci un'implementazione su come gestire gli aggiornamenti dello stato ricevuti.
  2. Estendi NotificationReceiverService e fornisci l'istanza CommandListener.
  3. Specifica il nome della classe dell'estensione NotificationReceiverService estesa 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
      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. Aggiungi il servizio a AndroidManifest.xml e assicurati che venga esportato.

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

Configurazione dei criteri

Per consentire all'app dell'estensione di comunicare direttamente con ADP, l'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 in corso

Test delle unità

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

Test di integrazione

Per il test con ADP saranno necessarie le seguenti informazioni:

  1. Nome del pacchetto dell'app dell'estensione.
  2. L'hash SHA-256 con codifica esadecimale della firma associata al pacchetto dell'app.
  3. Facoltativamente, in caso di test del callback: nome completo del servizio dal servizio appena introdotto per supportare il callback. (Nome completo di CommandService nell'esempio).