Интеграция с AMAPI SDK,Интеграция с AMAPI SDK

AMAPI SDK позволяет приложению расширения, указанному EMM, напрямую взаимодействовать с Android Device Policy. В настоящее время он включает поддержку локального выполнения Commands и только команду ClearAppData . Для интеграции с SDK необходимо предпринять следующие шаги:

  1. Добавьте библиотеку в приложение расширения .
  2. Используйте предоставленные API для подачи команд по мере необходимости.
  3. Добавьте элемент запросов , если целевой SDK >= 30.
  4. При желании вы можете предоставить реализацию службы для прослушивания обратных вызовов изменения статуса команды .
  5. Предоставьте устройству политику расширяемости .

Предварительные условия

  • Убедитесь, что для minSdkVersion приложения расширения установлен уровень API не ниже 21.

Добавление библиотеки в приложение-расширение

В файле build.gradle верхнего уровня добавьте репозиторий Google Maven, содержащий библиотеку SDK, к соответствующим модулям и добавьте зависимость к библиотеке:

repositories {
  ...
  google()
}

Затем добавьте библиотеку в блок зависимостей вашего модуля:

dependencies {
  implementation 'com.google.android.libraries.enterprise.amapi:amapi:1.0.0'
}

Отправлять запросы в политику устройств Android.

Теперь должно быть возможно отправлять запросы в ADP. Поддерживаются следующие запросы.

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

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

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

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

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

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

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

Добавление элемента запросов

Если ваше приложение предназначено для SDK 30 и более поздних версий, то в манифесте необходим элемент запросов, чтобы указать, что оно будет взаимодействовать с ADP.

<queries>
    <package android:name="com.google.android.apps.work.clouddpc" />
</queries>

Дополнительные сведения см. в разделе Фильтрация видимости пакетов на Android .

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

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

    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. Добавьте службу в свой AndroidManifest.xml и убедитесь, что она экспортирована.

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

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

 "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 — это интерфейс, поэтому тестирование позволяет легко предоставить тестируемую реализацию.

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

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

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