El SDK de la API de Android Management (AMAPI) permite que una app de extensión especificada por el EMM se comunique directamente con Android Device Policy (ADP) y ejecute Commands en el dispositivo.
En Integración con el SDK de la AMAPI, se proporciona más información sobre esta biblioteca y cómo agregarla a tu aplicación.
Una vez que se integra el SDK, la app de extensión puede comunicarse con ADP para hacer lo siguiente:
- enviar solicitudes de comandos
- consultar el estado de las solicitudes de comandos
- recibir cambios en el estado de los comandos
Emitir 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 para borrar los datos de la app para los paquetes especificados y esperar hasta que el comando se haya emitido correctamente. Si se emite correctamente, se devolverá 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 las solicitudes de comandos emitidas anteriormente. Para recuperar el estado de un comando, necesitarás el ID del comando (disponible en la solicitud del comando de emisión). En el siguiente fragmento, se muestra cómo enviar un GetCommandRequest al 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());
}
...
Detecta las devoluciones de llamada de cambio de estado del comando
De manera opcional, una app de extensión puede registrar una devolución de llamada para recibir actualizaciones sobre los cambios de estado de los comandos de ejecución prolongada siguiendo estos pasos:
- Los cambios de 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. - Extiende
NotificationReceiverServicey proporciona una instancia deCommandListenera través del métodogetCommandListener. Configura la política de la aplicación para asignarle el rol de
COMPANION_APP(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 public CommandListener getCommandListener() { // return the concrete implementation from previous step return ...; } }
Configuración de políticas
Para permitir que la app de extensión se comunique directamente con ADP, el EMM debe asignar el rol COMPANION_APP a la app con el campo roles en la política de la aplicación.
"applications": [{
"packageName": "com.amapi.extensibility.demo",
"installType": "FORCE_INSTALLED",
"roles": [
{ "roleType": "COMPANION_APP" }
]
}]
Para ver las opciones adicionales disponibles, consulta Aprovisiona el dispositivo con políticas de roles de la app.
Prueba
Pruebas de unidades
LocalCommandClient es una interfaz y, por lo tanto, permite proporcionar una implementación que se pueda probar.
Pruebas de integración
Se necesitará la siguiente información para realizar pruebas con ADP:
- Es el nombre del paquete de la app de extensión.
- Es el hash SHA-256 codificado en base64 de la firma asociada con el paquete de la app.
- De forma opcional, si se trata de una devolución de llamada de prueba, es el nombre completamente calificado del servicio del servicio recientemente introducido para admitir la devolución de llamada. (Nombre completamente calificado de
CommandServiceen el ejemplo).