O SDK da AMAPI permite que um
app de extensão especificado pelo EMM se comunique diretamente com o Android Device Policy.
Atualmente, ele inclui suporte para a execução local de
Commands
e apenas o comando ClearAppData
. Siga estas etapas para fazer a integração com o SDK:
- Adicionar biblioteca ao app de extensões
- Use as APIs fornecidas para emitir comandos conforme necessário.
- Adicione o elemento de consultas se o SDK de destino for maior ou igual a 30.
- Opcionalmente, forneça implementação do serviço para detectar callbacks de mudança do status do comando (em inglês).
- Provisione o dispositivo com a política de extensibilidade.
Pré-requisitos
- Confira se a minSdkVersion do app da extensão está definida como pelo menos o nível 21 da API.
Adicionar uma biblioteca ao aplicativo de extensão
No arquivo build.gradle de nível superior, adicione o repositório Maven do Google, que contém a biblioteca do SDK aos módulos relevantes e adicione a dependência à biblioteca:
repositories {
...
google()
}
Em seguida, adicione a biblioteca ao bloco de dependências do módulo:
dependencies {
implementation 'com.google.android.libraries.enterprise.amapi:amapi:1.0.0'
}
Enviar solicitações para o Android Device Policy
Agora deve ser possível enviar solicitações ao ADP. As solicitações a seguir são aceitas.
Emitir comando
O app da extensão pode solicitar que comandos sejam emitidos usando o ADP. IssueCommandRequest contém o objeto de solicitação com detalhes sobre o comando a ser emitido e parâmetros específicos. Confira mais informações sobre ele no Javadoc.
O snippet a seguir mostra como emitir uma solicitação para limpar os dados do pacote:
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();
}
...
O exemplo acima mostra a emissão de uma solicitação de dados do app claros para pacotes especificados e a espera até que o comando seja emitido. Se emitido com sucesso, um objeto Command será retornado com o status atual do comando e o ID do comando, que pode ser usado posteriormente para consultar o status de qualquer comando de longa duração.
Receber comando
O app de extensão também pode consultar o status de solicitações de comando emitidas anteriormente. Para recuperar o status de um comando, você vai precisar do ID do comando (disponível na solicitação de problema). O snippet a seguir mostra o envio de uma solicitação GetCommand para o 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());
}
...
Adicionando elemento de consultas
Se o app for direcionado ao SDK 30 e versões mais recentes, o elemento de consulta é necessário no manifesto para especificar que ele vai interagir com o ADP.
<queries>
<package android:name="com.google.android.apps.work.clouddpc" />
</queries>
Consulte Filtragem da visibilidade de pacotes no Android para mais informações.
Detectar callbacks de mudança de status do comando
- As mudanças de status do comando são notificadas ao CommandListener, implementa essa interface no app e fornece a implementação sobre como lidar com as atualizações de status recebidas.
- Estender NotificationReceiverService e fornecer a instância CommandListener.
Especifica o nome da classe do NotificationReceiverService estendido na política da API Android Management. Consulte "Configuração da política".
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 ...; } }
Adicione o serviço ao AndroidManifest.xml e verifique se ele foi exportado.
<service android:name = ".notification.SampleCommandService" android:exported = "true" />
Configuração de política
"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"
}
}]
Teste
Teste de unidade
O LocalCommandClient é uma interface e, portanto, o teste permite facilmente uma implementação testável.
Teste de integração
As informações a seguir serão necessárias para fazer testes com o Android Device Policy:
- Nome do pacote do app de extensão.
- O hash SHA-256 da assinatura associada ao pacote do app, codificado em hexadecimal.
- Opcionalmente, se for testar o callback: nome totalmente qualificado do serviço do serviço recém-introduzido para oferecer suporte ao callback. (Nome totalmente qualificado de CommandService no exemplo).