擴充功能應用程式和本機指令
透過集合功能整理內容
你可以依據偏好儲存及分類內容。
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 (可透過發出指令要求取得)。下列程式碼片段說明如何將 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());
}
...
監聽指令狀態變更回呼
擴充功能應用程式可以選擇註冊回呼,接收長時間執行指令的狀態變更更新內容,步驟如下:
- 系統會將指令狀態變更通知
CommandListener
,請在應用程式中實作這個介面,並提供如何處理收到的狀態更新的實作方式。
- 擴充
NotificationReceiverService
,並透過 getCommandListener
方法提供 CommandListener
例項。
在 Android Management API 政策中指定擴充 NotificationReceiverService
的類別名稱 (請參閱「政策設定」)。
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 進行測試:
- 擴充功能應用程式的套件名稱。
- 與應用程式套件相關聯的簽章十六進位編碼 SHA-256 雜湊。
- 選用:如果要測試回呼,請提供新推出的服務的完整服務名稱,以便支援回呼。(範例中
CommandService
的完整合格名稱)。
除非另有註明,否則本頁面中的內容是採用創用 CC 姓名標示 4.0 授權,程式碼範例則為阿帕契 2.0 授權。詳情請參閱《Google Developers 網站政策》。Java 是 Oracle 和/或其關聯企業的註冊商標。
上次更新時間:2025-07-26 (世界標準時間)。
[null,null,["上次更新時間:2025-07-26 (世界標準時間)。"],[[["\u003cp\u003eThe Android Management API (AMAPI) SDK enables extension apps to communicate directly with Android Device Policy (ADP) to execute commands on the device.\u003c/p\u003e\n"],["\u003cp\u003eThe SDK currently supports the \u003ccode\u003eClearAppData\u003c/code\u003e command, which allows for the clearing of specified app data.\u003c/p\u003e\n"],["\u003cp\u003eExtension apps can issue command requests to ADP, query the status of these requests, and receive updates on status changes through callbacks.\u003c/p\u003e\n"],["\u003cp\u003eTo enable communication between the extension app and ADP, the EMM must provide an \u003ccode\u003eextensionConfig\u003c/code\u003e policy that includes the extension app's package name, signing key fingerprint, and optionally, a notification receiver service.\u003c/p\u003e\n"],["\u003cp\u003eTesting can be achieved through unit testing with the \u003ccode\u003eLocalCommandClient\u003c/code\u003e interface, or through integration testing, using the package name, SHA-256 hash, and notification service.\u003c/p\u003e\n"]]],["The Android Management API (AMAPI) SDK allows an extension app to interact with Android Device Policy (ADP). It enables sending command requests, querying their status, and receiving status change callbacks. The SDK supports the `ClearAppData` command to clear specified apps' data. To issue a command, `IssueCommandRequest` is used, and the status can be retrieved with `GetCommandRequest`, providing a Command Id. The `CommandListener` interface and `NotificationReceiverService` class allow the app to receive updates on status changes. The `extensionConfig` policy, specified by an EMM, enables this communication.\n"],null,["# Extension apps and local commands\n\nThe Android Management API (AMAPI) SDK enables an EMM-specified extension app to\ncommunicate directly with Android Device Policy (ADP) and execute [`Commands`](/android/management/reference/amapi/com/google/android/managementapi/commands/package-summary)\non the device.\n| **Note:** Only the [`ClearAppData`](/android/management/reference/rest/v1/enterprises.devices/issueCommand#CommandType.ENUM_VALUES.CLEAR_APP_DATA) command is supported.\n\n[Integrate with the AMAPI SDK](/android/management/sdk-integration) provides more information about\nthis library and how to add it to your application.\n\nOnce integrated the SDK, your extension app can communicate with ADP to:\n\n- [send command requests](#issue_command)\n- [query the status of command requests](#get_command)\n- [receive command status changes](#listen_to_callbacks)\n\nIssue Command\n-------------\n\nAn extension app can request for commands to be issued using ADP.\n[`IssueCommandRequest`](/android/management/reference/amapi/com/google/android/managementapi/commands/model/IssueCommandRequest) contains the request object that will contain detail on\nthe command to be issued and specific parameters.\n\nThe following snippet shows how to issue a request to clear the package's data: \n\n import android.util.Log;\n ...\n import com.google.android.managementapi.commands.LocalCommandClientFactory;\n import com.google.android.managementapi.commands.model.Command;\n import com.google.android.managementapi.commands.model.GetCommandRequest;\n import com.google.android.managementapi.commands.model.IssueCommandRequest;\n import com.google.android.managementapi.commands.model.IssueCommandRequest.ClearAppsData;\n import com.google.common.collect.ImmutableList;\n import com.google.common.util.concurrent.FutureCallback;\n import com.google.common.util.concurrent.Futures;\n import com.google.common.util.concurrent.MoreExecutors;\n\n ...\n void issueClearAppDataCommand(ImmutableList\u003cString\u003e packageNames) {\n Futures.addCallback(\n LocalCommandClientFactory.create(getContext())\n .issueCommand(createClearAppRequest(packageNames)),\n new FutureCallback\u003cCommand\u003e() {\n @Override\n public void onSuccess(Command result) {\n // Process the returned command result here\n Log.i(TAG, \"Successfully issued command\");\n }\n\n @Override\n public void onFailure(Throwable t) {\n Log.e(TAG, \"Failed to issue command\", t);\n }\n },\n MoreExecutors.directExecutor());\n }\n\n IssueCommandRequest createClearAppRequest(ImmutableList\u003cString\u003e packageNames) {\n return IssueCommandRequest.builder()\n .setClearAppsData(\n ClearAppsData.builder()\n .setPackageNames(packageNames)\n .build()\n )\n .build();\n }\n ...\n\nThe earlier example shows issuing a clear app data request for specified\npackages and waiting until the command has been successfully issued. If\nsuccessfully issued, a `Command` object will be returned with the current\ncommand status and the command ID which can later be used to query the status of\nany long running commands.\n\nGet Command\n-----------\n\nAn extension app can query the status of previously issued command requests. To\nretrieve a command's status, you will need the command ID (available from the\nissue command request). The following snippet shows how to send a\n[`GetCommandRequest`](/android/management/reference/amapi/com/google/android/managementapi/commands/model/GetCommandRequest) to ADP. \n\n import android.util.Log;\n ...\n import com.google.android.managementapi.commands.LocalCommandClientFactory;\n ...\n import com.google.android.managementapi.commands.model.GetCommandRequest;\n import com.google.common.util.concurrent.FutureCallback;\n import com.google.common.util.concurrent.Futures;\n import com.google.common.util.concurrent.MoreExecutors;\n\n ...\n void getCommand(String commandId) {\n Futures.addCallback(\n LocalCommandClientFactory.create(getApplication())\n .getCommand(GetCommandRequest.builder().setCommandId(commandId).build()),\n new FutureCallback\u003cCommand\u003e() {\n @Override\n public void onSuccess(Command result) {\n // Process the returned command result here\n Log.i(Constants.TAG, \"Successfully issued command\");\n }\n\n @Override\n public void onFailure(Throwable t) {\n Log.e(Constants.TAG, \"Failed to issue command\", t);\n }\n },\n MoreExecutors.directExecutor());\n }\n ...\n\nListen to Command status change callbacks\n-----------------------------------------\n\nAn extension app can optionally register a callback to receive updates for\nstatus changes of long running commands following these steps:\n\n1. Command status changes are notified to [`CommandListener`](/android/management/reference/amapi/com/google/android/managementapi/commands/CommandListener), implement this interface in your app and provide implementation on how to handle the received status updates.\n2. Extend [`NotificationReceiverService`](/android/management/sdk-integration#notification_receiver_service) and provide a `CommandListener` instance through the `getCommandListener` method.\n3. Specify class name of extended `NotificationReceiverService` in the Android\n Management API policy ([see Policy Configuration](#policy)).\n\n import com.google.android.managementapi.commands.CommandListener;\n import com.google.android.managementapi.notification.NotificationReceiverService;\n\n ...\n\n public class SampleCommandService extends NotificationReceiverService {\n\n @Override\n public CommandListener getCommandListener() {\n // return the concrete implementation from previous step\n return ...;\n }\n }\n\nPolicy Configuration\n--------------------\n\nTo enable the extension app to communicate directly with ADP, the EMM has to\nprovide an [`extensionConfig`](/android/management/reference/rest/v1/enterprises.policies#ExtensionConfig) policy. \n\n \"applications\": [{\n \"packageName\": \"com.amapi.extensibility.demo\",\n ...\n \"extensionConfig\": {\n \"signingKeyFingerprintsSha256\": [\n // Include signing key of extension app\n ],\n // Optional if callback is implemented\n \"notificationReceiver\": \"com.amapi.extensibility.demo.notification.SampleCommandService\"\n }\n }]\n\n### Testing\n\n#### Unit testing\n\n[`LocalCommandClient`](/android/management/reference/amapi/com/google/android/managementapi/commands/LocalCommandClient) is an interface and thus allows to provide a testable\nimplementation.\n\n#### Integration testing\n\nThe following information will be needed to test with ADP:\n\n1. Package name of the extension app.\n2. The hex-encoded SHA-256 hash of the Signature associated with the app package.\n3. Optionally, if testing callback - fully qualified name of the service from the newly introduced service to support callback. (Fully qualified name of `CommandService` in the example)."]]