Приложения расширения и локальные команды

SDK Android Management API (AMAPI) позволяет приложению расширения, указанному в EMM, напрямую взаимодействовать с Android Device Policy (ADP) и выполнять Commands на устройстве.

Интеграция с AMAPI SDK предоставляет более подробную информацию об этой библиотеке и о том, как добавить ее в ваше приложение.

После интеграции SDK ваше приложение расширения сможет взаимодействовать с ADP для:

Выдать команду

Приложение расширения может запрашивать выдачу команд с использованием ADP. IssueCommandRequest содержит объект запроса, который будет содержать подробную информацию о выдаваемой команде и конкретных параметрах.

В следующем фрагменте показано, как выполнить запрос на очистку данных пакета:

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

В предыдущем примере показана выдача запроса на очистку данных приложения для указанных пакетов и ожидание успешного выполнения команды. В случае успешного выполнения будет возвращен объект Command с текущим статусом команды и идентификатором команды, который впоследствии можно использовать для запроса статуса любых длительно выполняющихся команд.

Получить команду

Приложение расширения может запрашивать статус ранее выданных запросов команд. Чтобы получить статус команды, вам понадобится идентификатор команды (доступный из запроса команды issue). В следующем фрагменте показано, как отправить GetCommandRequest в 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());
  }
  ...

Прослушивание обратных вызовов изменения статуса команды

Приложение расширения может дополнительно зарегистрировать обратный вызов для получения обновлений об изменениях статуса длительно выполняемых команд, выполнив следующие действия:

  1. Изменения статуса команды передаются в CommandListener . Реализуйте этот интерфейс в своем приложении и предоставьте реализацию того, как обрабатывать полученные обновления статуса.
  2. Расширьте NotificationReceiverService и предоставьте экземпляр CommandListener через метод getCommandListener .
  3. Укажите имя класса расширенной NotificationReceiverService в политике API управления Android ( см. Конфигурация политики ).

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

Конфигурация политики

Чтобы приложение расширения могло напрямую взаимодействовать с ADP, EMM должна предоставить политику 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"
   }
 }]

Тестирование

Модульное тестирование

LocalCommandClient — это интерфейс, позволяющий обеспечить тестируемую реализацию.

Интеграционное тестирование

Для тестирования с помощью ADP потребуется следующая информация:

  1. Имя пакета приложения расширения.
  2. Шестнадцатеричный хэш SHA-256 подписи, связанной с пакетом приложения.
  3. Необязательно, если тестируется обратный вызов - полное имя службы из недавно представленной службы для поддержки обратного вызова. (Полное имя CommandService в примере).