Ważne: nie przyjmujemy już nowych rejestracji w interfejsie Play EMM API.
Więcej informacji
Wyślij żądania zbiorcze
Zadbaj o dobrą organizację dzięki kolekcji
Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.
Z tego dokumentu dowiesz się, jak grupować wywołania interfejsu API, aby zmniejszyć liczbę połączeń, które musi nawiązać klient.
Ten dokument dotyczy przede wszystkim tworzenia żądań zbiorczych za pomocą biblioteki klienta w języku Java.
Podstawowy przykład jest również dostępny w
Biblioteka klienta interfejsu API Google dla .NET. System wsadowy interfejsu Google Play EMM API używa tego samego protokołu HTTP.
jako system przetwarzania wsadowego OData.
Omówienie
Każde żądanie wysyłane przez klienta do interfejsu Google Play EMM API skutkuje określonym nakładem pracy. Interfejs Google Play EMM API obsługuje grupowanie, dzięki czemu klient może umieścić kilka wywołań interfejsu API w jednym żądaniu.
Oto kilka przykładów sytuacji, w których warto użyć grupowania:
- Domena została właśnie zarejestrowana i teraz ma jeszcze dużo danych do przesłania.
- Użytkownik wprowadził zmiany w danych, gdy aplikacja działała w trybie offline, dlatego aplikacja musi zsynchronizować znaczną ilość danych lokalnych z serwerem.
W takich przypadkach zamiast wysyłać każde połączenie z osobna, możesz zgrupować je w jedną prośbę. Możesz nawet grupować żądania dotyczące wielu użytkowników lub wielu interfejsów API Google.
Obowiązuje jednak ograniczenie do 1000 wywołań w jednym żądaniu zbiorczym. Jeśli musisz wykonać więcej połączeń, użyj kilku żądań zbiorczych.
Szczegóły wsadu
Żądanie zbiorcze składa się z wielu wywołań interfejsu API połączonych w jedno żądanie JSON-RPC. W tej sekcji szczegółowo opisujemy składnię żądań zbiorczych. Przykład znajdziesz w sekcji poniżej.
Uwaga: zbiór n zbiorczych żądań wlicza się do limitu wykorzystania jako żądania n, a nie jako jedno żądanie. Przed przetworzeniem żądanie zbiorcze jest dzielone na zbiór żądań.
Biblioteka klienta Java zawiera wywołania służące do tworzenia żądań dla każdego wywołania interfejsu Google Play EMM API. Aby na przykład wyświetlić listę wszystkich aplikacji zainstalowanych na urządzeniu, należy użyć następującego polecenia:
AndroidEnterprise enterprise = ...;
InstallsListResponse response = enterprise.installs().list(enterpriseId, userId, deviceId)
.execute();
Istnieje dodatkowe połączenie batch()
, które może pojawić się w kolejce kilku żądań. Przykład:
AndroidEnterprise enterprise = ...;
BatchRequest batchRequest = enterprise.batch();
enterprise.installs().list(enterpriseId, userId, deviceId1).queue(batchRequest, callback1);
enterprise.installs().list(enterpriseId, userId, deviceId2).queue(batchRequest, callback2);
enterprise.installs().list(enterpriseId, userId, deviceId3).queue(batchRequest, callback3);
batchRequest.execute();
Po wywołaniu batchRequest.execute()
wszystkie żądania oczekujące w kolejce są wysyłane do serwera jednocześnie w postaci tablicy JSON. Serwer stosuje do każdej części parametry zapytania i nagłówki żądania zewnętrznego (odpowiednio) do każdej części, a następnie traktuje każdą część tak, jakby była to osobne żądanie JSON.
Odpowiedź na żądanie zbiorcze
Serwer wykonuje każde osobne żądanie i grupuje wynik w pojedynczą odpowiedź wykonaną z pojedynczej tablicy. Biblioteka klienta dzieli tę odpowiedź na poszczególne odpowiedzi, które są wysyłane do funkcji wywołania zwrotnego przekazywanej do queue()
. Wywołanie zwrotne to interfejs określający metodę w przypadku niepowodzenia i metodę sukcesu. Metoda callback1
zostałaby zaimplementowana na przykład jako:
private class InstallsCallback implements JsonBatchCallback<InstallsListResponse> {
@Override
public void onSuccess(InstallsListResponse response, HttpHeaders responseHeaders) {
...
}
@Override
public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) {
...
}
}
Uwaga: serwer może wykonywać wywołania w dowolnej kolejności, więc nie należy polegać na otrzymywaniu wyników w kolejności określonej w żądaniu. Jeśli chcesz mieć pewność, że w danej kolejności będą wykonywane 2 wywołania, nie możesz ich wysłać w jednym żądaniu. wyślij pierwsze żądanie i poczekaj na odpowiedź, zanim wyślesz kolejne.
Przykładowe żądanie zbiorcze
W tym przykładzie pokazujemy, jak wyświetlić listę wszystkich aplikacji zainstalowanych na wszystkich urządzeniach danego użytkownika. Pierwsze wywołania służą do uzyskania identyfikatora firmy i użytkownika, więc muszą być wykonywane po kolei. Gdy enterprise.devices().list()
uzyska wszystkie identyfikatory urządzeń, możemy wysłać żądanie zbiorcze, by pobrać wszystkie aplikacje na wszystkich urządzeniach użytkownika jednocześnie.
package com.google.playenterprise.example;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.client.googleapis.batch.json.JsonBatchCallback;
import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.androidenterprise.AndroidEnterprise;
import com.google.api.services.androidenterprise.AndroidEnterprise.Installs;
import com.google.api.services.androidenterprise.AndroidEnterpriseScopes;
import com.google.api.services.androidenterprise.model.Device;
import com.google.api.services.androidenterprise.model.DevicesListResponse;
import com.google.api.services.androidenterprise.model.Enterprise;
import com.google.api.services.androidenterprise.model.Install;
import com.google.api.services.androidenterprise.model.InstallsListResponse;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* Lists all the apps installed on all devices of a given user.
*/
public class ListAllInstalls {
private AndroidEnterprise enterprise;
private final List<String> installList = new ArrayList<>();
public static void main(String[] argv) throws Exception {
if (argv.length != 2) {
throw new IllegalArgumentException("Usage: ListAllInstalls email jsonFilename");
} else if (!argv[0].contains("@")) {
throw new IllegalArgumentException("First parameter should be a valid email.");
}
new ListAllInstalls().run(argv[0], argv[1]);
}
private void run(String userEmail, String jsonKeyPath) throws IOException {
enterprise = createAndroidEnterprise(jsonKeyPath);
// Get the enterprise id, user id, and user devices.
String domain = userEmail.split("@")[1];
List<Enterprise> results = enterprise.enterprises().list(domain).execute().getEnterprise();
if (results.isEmpty()) {
throw new RuntimeException("No enterprise found.");
}
String enterpriseId = results.get(0).getId();
String userId = enterprise
.users()
.list(enterpriseId, userEmail)
.execute()
.getUser()
.get(0)
.getId();
List<Device> devices = getAllDevices(enterpriseId, userId);
// Batch all calls to get installs on all user devices.
gatherAllInstalls(enterpriseId, userId, devices);
for (String entry : installList) {
// Do something.
System.out.println(entry);
}
}
private List<Device> getAllDevices(String enterpriseId, String userId) throws IOException {
DevicesListResponse devices = enterprise.devices().list(enterpriseId, userId).execute();
return devices.getDevice();
}
private void gatherAllInstalls(String enterpriseId, String userId, List<Device> devices)
throws IOException {
BatchRequest batchRequest = enterprise.batch();
for (Device device : devices) {
Installs.List list = enterprise
.installs().list(enterpriseId, userId, device.getAndroidId());
// Each callback can take the specifics of the associated request in its constructor.
list.queue(batchRequest, new InstallsCallback(device.getAndroidId()));
}
// Executes all the queued requests and their callbacks, single-threaded.
batchRequest.execute();
}
private class InstallsCallback extends JsonBatchCallback<InstallsListResponse> {
private final String androidId;
InstallsCallback(String androidId) {
this.androidId = androidId;
}
@Override
public void onSuccess(InstallsListResponse response, HttpHeaders responseHeaders) {
for (Install install : response.getInstall()) {
installList.add(androidId + "," + install.getProductId());
}
}
@Override
public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) {
throw new RuntimeException("Error fetching a device");
}
}
private AndroidEnterprise createAndroidEnterprise(String jsonKeyPath) throws IOException {
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
InputStream is = new BufferedInputStream(new FileInputStream(jsonKeyPath));
final Credential credential = GoogleCredential.fromStream(is, httpTransport, jsonFactory)
.createScoped(AndroidEnterpriseScopes.all());
HttpRequestInitializer httpRequestInitializer = new HttpRequestInitializer() {
@Override
public void initialize(HttpRequest request) throws IOException {
credential.initialize(request);
}
};
return new AndroidEnterprise.Builder(httpTransport, jsonFactory, httpRequestInitializer)
.build();
}
}
O ile nie stwierdzono inaczej, treść tej strony jest objęta licencją Creative Commons – uznanie autorstwa 4.0, a fragmenty kodu są dostępne na licencji Apache 2.0. Szczegółowe informacje na ten temat zawierają zasady dotyczące witryny Google Developers. Java jest zastrzeżonym znakiem towarowym firmy Oracle i jej podmiotów stowarzyszonych.
Ostatnia aktualizacja: 2025-05-08 UTC.
[null,null,["Ostatnia aktualizacja: 2025-05-08 UTC."],[[["\u003cp\u003eBatching API calls in the Google Play EMM API reduces overhead by combining multiple calls into a single HTTP request.\u003c/p\u003e\n"],["\u003cp\u003eThis document focuses on batch requests using the Java client library, with an example demonstrating how to list all apps installed on a user's devices.\u003c/p\u003e\n"],["\u003cp\u003eBatch requests are limited to 1000 calls and count toward usage limits as individual requests.\u003c/p\u003e\n"],["\u003cp\u003eThe server may process batched calls in any order, requiring separate requests for sequential execution.\u003c/p\u003e\n"],["\u003cp\u003eResponses to batch requests are handled by callbacks defined for each individual request within the batch.\u003c/p\u003e\n"]]],[],null,["# Send Batch Requests\n\nThis document shows how to batch API calls together to reduce the number of connections your client has to make.\n\nThis document is specifically about making a batch request using the Java client library.\nA basic example is also available in the [Google API Client Library for .NET](https://developers.google.com/api-client-library/dotnet/guide/batch). The batch system for the Google Play EMM API uses the same HTTP\nsyntax as the [OData batch processing](http://www.odata.org/documentation/odata-version-3-0/batch-processing/) system.\n\nOverview\n--------\n\nEach request that your client makes via the Google Play EMM API results in a certain amount of overhead. The Google Play EMM API supports batching, to allow your client to put several API calls into a single request.\n\nHere are some examples of situations in which you might want to use batching:\n\n- A domain has just been enrolled and now has a lot of data to upload.\n- A user made changes to data while your application was offline, so your application needs to synchronize a great deal of local data with the server.\n\nIn cases such as these, instead of sending each call separately you can group them together into a single request. You can even group requests for multiple users, or for multiple Google APIs.\n\nYou are, however, limited to 1000 calls in a single batch request. If you need to make more calls than that, use multiple batch requests.\n\nBatch details\n-------------\n\nA batch request consists of multiple API calls combined into one JSON-RPC request. This section describes the batch request syntax in detail, with an [example](#example) in the section following.\n\n**Note** : A set of \u003cvar translate=\"no\"\u003en\u003c/var\u003e requests batched together counts toward your usage limit as \u003cvar translate=\"no\"\u003en\u003c/var\u003e requests, not as one request. The batch request is taken apart into a set of requests before processing.\n\n### Format of a batch request\n\nThe Java client library contains calls to create requests for each Google Play EMM API call. For instance, to list all apps installed on a device, you would use the following: \n\n```\nAndroidEnterprise enterprise = ...;\nInstallsListResponse response = enterprise.installs().list(enterpriseId, userId, deviceId)\n .execute();\n```\n\nThere is an additional `batch()` call that can queue several requests, as seen here: \n\n```\nAndroidEnterprise enterprise = ...;\nBatchRequest batchRequest = enterprise.batch();\nenterprise.installs().list(enterpriseId, userId, deviceId1).queue(batchRequest, callback1);\nenterprise.installs().list(enterpriseId, userId, deviceId2).queue(batchRequest, callback2);\nenterprise.installs().list(enterpriseId, userId, deviceId3).queue(batchRequest, callback3);\nbatchRequest.execute();\n```\nWhen `batchRequest.execute()` is called, all the queued requests are sent at once to the server as a JSON array. The server applies the outer request's query parameters and headers (as appropriate) to each part, and then treats each part as if it were a separate JSON request.\n\n\u003cbr /\u003e\n\n### Response to a batch request\n\nThe server executes each separate request, and groups the result into single response made of a single array. The client library splits this response into individual responses, and each one is sent to the callback function passed to `queue()`. The callback is an interface defining a method for failure and a method for success. For instance, `callback1` would be implemented as an instance of the following: \n\n```\nprivate class InstallsCallback implements JsonBatchCallback\u003cInstallsListResponse\u003e {\n\n @Override\n public void onSuccess(InstallsListResponse response, HttpHeaders responseHeaders) {\n ...\n }\n\n @Override\n public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) {\n ...\n }\n}\n```\n\n**Note**: The server may perform your calls in any order, so don't rely on receiving results in the order specified in your request. If you want to ensure that two calls occur in a given order, you can't send them in a single request; instead, send the first request by itself, and wait for a response before sending the second.\n\nExample batch request\n---------------------\n\nThe following example shows how to list all the apps installed on all of a given user devices. The first calls are used to obtain the id of the enterprise and of the user, and accordingly must be executed sequentially. Once all the device ids have been obtained with `enterprise.devices().list()`, we can do a batch request to retrieve all of the applications on all the user's devices at once. \n\n```\npackage com.google.playenterprise.example;\n\nimport com.google.api.client.auth.oauth2.Credential;\nimport com.google.api.client.googleapis.auth.oauth2.GoogleCredential;\nimport com.google.api.client.googleapis.batch.BatchRequest;\nimport com.google.api.client.googleapis.batch.json.JsonBatchCallback;\nimport com.google.api.client.googleapis.json.GoogleJsonError;\nimport com.google.api.client.http.HttpHeaders;\nimport com.google.api.client.http.HttpRequest;\nimport com.google.api.client.http.HttpRequestInitializer;\nimport com.google.api.client.http.HttpTransport;\nimport com.google.api.client.http.javanet.NetHttpTransport;\nimport com.google.api.client.json.JsonFactory;\nimport com.google.api.client.json.jackson.JacksonFactory;\nimport com.google.api.services.androidenterprise.AndroidEnterprise;\nimport com.google.api.services.androidenterprise.AndroidEnterprise.Installs;\nimport com.google.api.services.androidenterprise.AndroidEnterpriseScopes;\nimport com.google.api.services.androidenterprise.model.Device;\nimport com.google.api.services.androidenterprise.model.DevicesListResponse;\nimport com.google.api.services.androidenterprise.model.Enterprise;\nimport com.google.api.services.androidenterprise.model.Install;\nimport com.google.api.services.androidenterprise.model.InstallsListResponse;\n\nimport java.io.BufferedInputStream;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Lists all the apps installed on all devices of a given user.\n */\npublic class ListAllInstalls {\n private AndroidEnterprise enterprise;\n private final List\u003cString\u003e installList = new ArrayList\u003c\u003e();\n\n public static void main(String[] argv) throws Exception {\n if (argv.length != 2) {\n throw new IllegalArgumentException(\"Usage: ListAllInstalls email jsonFilename\");\n } else if (!argv[0].contains(\"@\")) {\n throw new IllegalArgumentException(\"First parameter should be a valid email.\");\n }\n new ListAllInstalls().run(argv[0], argv[1]);\n }\n\n private void run(String userEmail, String jsonKeyPath) throws IOException {\n enterprise = createAndroidEnterprise(jsonKeyPath);\n\n // Get the enterprise id, user id, and user devices.\n String domain = userEmail.split(\"@\")[1];\n List\u003cEnterprise\u003e results = enterprise.enterprises().list(domain).execute().getEnterprise();\n if (results.isEmpty()) {\n throw new RuntimeException(\"No enterprise found.\");\n }\n String enterpriseId = results.get(0).getId();\n String userId = enterprise\n .users()\n .list(enterpriseId, userEmail)\n .execute()\n .getUser()\n .get(0)\n .getId();\n List\u003cDevice\u003e devices = getAllDevices(enterpriseId, userId);\n\n // Batch all calls to get installs on all user devices.\n gatherAllInstalls(enterpriseId, userId, devices);\n\n for (String entry : installList) {\n // Do something.\n System.out.println(entry);\n }\n }\n\n private List\u003cDevice\u003e getAllDevices(String enterpriseId, String userId) throws IOException {\n DevicesListResponse devices = enterprise.devices().list(enterpriseId, userId).execute();\n return devices.getDevice();\n }\n\n private void gatherAllInstalls(String enterpriseId, String userId, List\u003cDevice\u003e devices)\n throws IOException {\n BatchRequest batchRequest = enterprise.batch();\n for (Device device : devices) {\n Installs.List list = enterprise\n .installs().list(enterpriseId, userId, device.getAndroidId());\n // Each callback can take the specifics of the associated request in its constructor.\n list.queue(batchRequest, new InstallsCallback(device.getAndroidId()));\n }\n // Executes all the queued requests and their callbacks, single-threaded.\n batchRequest.execute();\n }\n\n private class InstallsCallback extends JsonBatchCallback\u003cInstallsListResponse\u003e {\n private final String androidId;\n\n InstallsCallback(String androidId) {\n this.androidId = androidId;\n }\n\n @Override\n public void onSuccess(InstallsListResponse response, HttpHeaders responseHeaders) {\n for (Install install : response.getInstall()) {\n installList.add(androidId + \",\" + install.getProductId());\n }\n }\n\n @Override\n public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) {\n throw new RuntimeException(\"Error fetching a device\");\n }\n }\n\n private AndroidEnterprise createAndroidEnterprise(String jsonKeyPath) throws IOException {\n HttpTransport httpTransport = new NetHttpTransport();\n JsonFactory jsonFactory = new JacksonFactory();\n\n InputStream is = new BufferedInputStream(new FileInputStream(jsonKeyPath));\n final Credential credential = GoogleCredential.fromStream(is, httpTransport, jsonFactory)\n .createScoped(AndroidEnterpriseScopes.all());\n\n HttpRequestInitializer httpRequestInitializer = new HttpRequestInitializer() {\n @Override\n public void initialize(HttpRequest request) throws IOException {\n credential.initialize(request);\n }\n };\n return new AndroidEnterprise.Builder(httpTransport, jsonFactory, httpRequestInitializer)\n .build();\n }\n}\n```"]]