Ten dokument pokazuje, jak łączyć wywołania interfejsu API, aby zmniejszyć liczbę połączeń, które musi nawiązać klient.
Ten dokument dotyczy wysyłania żądań zbiorczych za pomocą biblioteki klienta w języku Java. Podstawowy przykład znajdziesz w bibliotece klientów interfejsu Google API dla systemu .NET. System wsadowy interfejsu Google Play EMM API korzysta z tej samej składni HTTP co system zbiorczego przetwarzania danych O.
Omówienie
Każde żądanie wysyłane przez klienta za pomocą interfejsu Google Play EMM API wiąże się z określonym narzutem. Interfejs Google Play EMM API obsługuje wsadowe, aby Twój klient mógł wysyłać kilka wywołań interfejsu API do jednego żądania.
Oto kilka przykładów sytuacji, w których może być przydatna funkcja grupowania:
- Domena została zarejestrowana i ma teraz dużo danych do przesłania.
- Użytkownik wprowadził dane w trybie offline, więc aplikacja musi zsynchronizować z serwerem wiele danych lokalnych.
W takich przypadkach zamiast wysyłać każde wywołanie oddzielnie, możesz połączyć je w jedno żądanie. Możesz nawet grupować żądania dla wielu użytkowników lub wielu interfejsów API Google.
W jednym żądaniu zbiorczym można jednak utworzyć maksymalnie 1000 połączeń. Jeśli chcesz 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. Ta sekcja szczegółowo opisuje składnię żądań zbiorczych, a w poniższej sekcji przedstawiamy przykład.
Uwaga: zestaw n żądań zbiorczych wlicza się do limitu wykorzystania jako n żądań, a nie jako jedno żądanie. Żądanie zbiorcze jest przed przetwarzaniem rozdzielane na zestaw żądań.
Format żądania zbiorczego
Biblioteka klienta w Javie zawiera wywołania potrzebne do utworzenia każdego wywołania interfejsu API Google Play EMM API. Aby na przykład wyświetlić wszystkie aplikacje zainstalowane na urządzeniu, trzeba by użyć:
AndroidEnterprise enterprise = ...; InstallsListResponse response = enterprise.installs().list(enterpriseId, userId, deviceId) .execute();
Istnieje dodatkowe wywołanie batch()
, które może umieszczać w kolejce kilka żądań, jak pokazano tutaj:
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 w kolejce są wysyłane do serwera jednocześnie jako tablica JSON. Serwer stosuje parametry i nagłówki zapytania zewnętrznego do każdej części, a następnie traktuje każdą część jak osobne żądanie JSON.
Odpowiedź na żądanie zbiorcze
Serwer wykonuje każde osobne żądanie i grupuje wynik w pojedynczą odpowiedź utworzoną w ramach jednej tablicy. Biblioteka klienta dzieli tę odpowiedź na poszczególne odpowiedzi, a każda z nich jest wysyłana do funkcji wywołania zwrotnego przekazywanej do queue()
. Wywołanie zwrotne to interfejs definiujący metodę niepowodzenia i metodę sukcesu. Na przykład callback1
może być zaimplementowany jako wystąpienie tego kodu:
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 możesz otrzymywać wyników w określonej kolejności. Jeśli chcesz mieć pewność, że dwa wywołania występują w jednej kolejności, nie możesz wysłać ich w ramach jednego żądania. Zamiast tego wyślij pierwsze żądanie i poczekaj na odpowiedź, zanim wyślesz drugie.
Przykładowe żądanie zbiorcze
Poniższy przykład pokazuje, jak wyświetlić listę wszystkich aplikacji zainstalowanych na danym urządzeniu użytkownika. Pierwsze wywołania są używane w celu uzyskania identyfikatora firmy i użytkownika, dlatego muszą być wykonywane po kolei. Gdy identyfikatory urządzenia zostaną uzyskane przy użyciu enterprise.devices().list()
, możemy wysłać żądanie zbiorcze, aby pobrać wszystkie aplikacje na wszystkie urządzenia 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(); } }