Apps de extensiones y comandos locales

El SDK de la API de administración de Android (AMAPI) permite que una app de extensión especificada por EMM se comunique directamente con Android Device Policy (ADP) y ejecute Commands en el dispositivo.

En Integrar con el SDK de AMAPI, se proporciona más información sobre esta biblioteca y cómo agregarla a tu aplicación.

Una vez integrado el SDK, tu app de extensión puede comunicarse con ADP con lo siguiente:

Ejecutar comando

Una app de extensión puede solicitar que se emitan comandos con ADP. IssueCommandRequest contiene el objeto de solicitud que incluirá detalles sobre el comando que se emitirá y los parámetros específicos.

En el siguiente fragmento, se muestra cómo emitir una solicitud para borrar los datos del paquete:

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

En el ejemplo anterior, se muestra cómo emitir una solicitud clara de datos de la app para paquetes especificados y esperar a que el comando se emita de forma correcta. Si se emite correctamente, se mostrará un objeto Command con el estado actual del comando y el ID del comando, que se puede usar más adelante para consultar el estado de cualquier comando de larga duración.

Obtener comando

Una app de extensión puede consultar el estado de solicitudes de comando emitidas anteriormente. Para recuperar el estado de un comando, necesitarás el ID del comando (disponible en la solicitud de comando de emisión). En el siguiente fragmento, se muestra cómo enviar un GetCommandRequest a 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());
  }
  ...

Escucha las devoluciones de llamada de cambio de estado de los comandos

Una app de extensión puede registrar una devolución de llamada para recibir actualizaciones de los cambios de estado de los comandos de larga duración mediante estos pasos:

  1. Los cambios en el estado del comando se notifican a CommandListener. Implementa esta interfaz en tu app y proporciona una implementación sobre cómo controlar las actualizaciones de estado recibidas.
  2. Extiende NotificationReceiverService y proporciona la instancia de CommandListener.
  3. Especifica el nombre de clase de la NotificationReceiverService extendida en la política de la API de administración de Android (consulta Configuración de políticas).

    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. Agrega el servicio a tu AndroidManifest.xml y asegúrate de que se exporte.

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

Configuración de políticas

Para permitir que la app de extensión se comunique directamente con ADP, la EMM debe proporcionar una política 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"
   }
 }]

Prueba

Pruebas de unidades

LocalCommandClient es una interfaz y, por lo tanto, permite proporcionar una implementación que se puede probar.

Pruebas de integración

Se necesitará la siguiente información para realizar pruebas con ADP:

  1. Nombre del paquete de la extensión de la app.
  2. El hash SHA-256 con codificación hexadecimal de la firma asociada con el paquete de la app.
  3. De manera opcional, si se prueba la devolución de llamada: Es el nombre completamente calificado del servicio del servicio recién introducido para admitir la devolución de llamada. (Nombre completamente calificado de CommandService en el ejemplo).