扩展程序应用和本地命令

借助 Android Management API (AMAPI) SDK,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 对象,其中包含当前命令状态和命令 ID,稍后可用于查询任何长时间运行的命令的状态。

获取命令

扩展程序应用可以查询以前发出的命令请求的状态。如需检索命令的状态,您需要使用问题命令请求中提供的命令 ID。以下代码段展示了如何向 ADP 发送 GetCommandRequest

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 实例。
  3. 在 Android Management API 政策中指定扩展 NotificationReceiverService 的类名称(请参阅政策配置)。

    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" />
    

策略配置

为了让扩展程序应用能够直接与 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 的完全限定名称)。