Toplu İstek Gönderme

Bu belgede, istemcinizin yapması gereken bağlantı sayısını azaltmak için API çağrılarının nasıl toplu olarak kullanılacağı gösterilmektedir.

Bu belge özel olarak, Java istemci kitaplığını kullanarak toplu istek yapma hakkındadır. Basit bir örnek için de .NET için Google API İstemci Kitaplığı. Google Play EMM API'sinin toplu sistemi aynı HTTP'yi kullanır söz dizimini OData toplu işleme sistemiyle belirtebilirsiniz.

Genel Bakış

İstemcinizin Google Play EMM API üzerinden yaptığı her istek, belirli bir miktarda ek yüke neden olur. Google Play EMM API, istemcinizin tek bir isteğe birden fazla API çağrısı yerleştirmesine olanak tanımak için toplu işlemeyi destekler.

Aşağıda, toplu işlemeyi kullanmak isteyebileceğiniz durumlara ilişkin bazı örnekler verilmiştir:

  • Bir alan kısa süre önce kaydedildi ve artık yüklenecek çok fazla veri var.
  • Uygulamanız çevrimdışıyken bir kullanıcı verilerde değişiklik yaptığından, uygulamanızın, yerel verilerin büyük bir kısmını sunucuyla senkronize etmesi gerekir.

Bu gibi durumlarda her çağrıyı ayrı ayrı göndermek yerine tek bir istek altında gruplandırabilirsiniz. Birden fazla kullanıcı veya birden fazla Google API'si için istekleri bile gruplandırabilirsiniz.

Ancak tek bir toplu istekte 1.000 çağrıyla sınırlıdır. Bundan daha fazla çağrı yapmanız gerekiyorsa birden çok toplu istek kullanın.

Grup ayrıntıları

Toplu istek, bir JSON-RPC isteğinde birleştirilen birden çok API çağrısından oluşur. Bu bölümde, toplu istek söz dizimi, takip eden bölümde bir örnek ile ayrıntılı olarak açıklanmaktadır.

Not: Gruplandırılmış n istekleri, kullanım sınırınıza tek bir istek olarak değil n isteği olarak dahil edilir. Toplu istek, işlenmeden önce bir dizi isteğe ayrılır.

Toplu isteğin biçimi

Java istemci kitaplığı, her Google Play EMM API çağrısı için istek oluşturma çağrıları içerir. Örneğin, bir cihazda yüklü tüm uygulamaları listelemek için aşağıdakileri kullanırsınız:

AndroidEnterprise enterprise = ...;
InstallsListResponse response = enterprise.installs().list(enterpriseId, userId, deviceId)
  .execute();

Aşağıda gösterildiği gibi, çeşitli istekleri sıraya koyabilecek ek bir batch() çağrısı vardır:

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();
. batchRequest.execute() çağrıldığında, sıraya alınan tüm istekler aynı anda sunucuya bir JSON dizisi olarak gönderilir. Sunucu, dış isteğin sorgu parametrelerini ve başlıklarını (uygun şekilde) her bölüme uygular ve daha sonra her bölümü ayrı bir JSON isteğiymiş gibi işler.

Toplu isteğe yanıt verme

Sunucu her ayrı isteği yürütür ve sonucu tek bir diziden oluşan tek bir yanıtta gruplandırır. İstemci kitaplığı bu yanıtı bağımsız yanıtlara böler ve her yanıt queue() işlevine iletilen geri çağırma işlevine gönderilir. Geri çağırma, başarısızlık yöntemi ve başarı yöntemi tanımlayan bir arayüzdür. Örneğin callback1, aşağıdakilerin bir örneği olarak uygulanır:

private class InstallsCallback implements JsonBatchCallback<InstallsListResponse> {

  @Override
  public void onSuccess(InstallsListResponse response, HttpHeaders responseHeaders) {
    ...
  }

  @Override
  public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) {
    ...
  }
}

Not: Sunucu, çağrılarınızı herhangi bir sırada gerçekleştirebileceği için sonuçların isteğinizde belirtilen sırayla alınacağına güvenmeyin. İki çağrının belirli bir sırada gerçekleşmesini istiyorsanız bunları tek bir istekte gönderemezsiniz. bunun yerine ilk isteği tek başına gönderin, ikinci isteği göndermeden önce yanıt almayı bekleyin.

Örnek toplu istek

Aşağıdaki örnekte, belirli bir kullanıcı cihazının tümünde yüklü tüm uygulamaların nasıl listeleneceği gösterilmektedir. İlk çağrılar kuruluşun ve kullanıcının kimliğini almak için kullanılır ve buna göre sırayla yürütülmelidir. enterprise.devices().list() ile tüm cihaz kimlikleri alındıktan sonra, kullanıcının tüm cihazlarındaki uygulamaların hepsini aynı anda almak için toplu bir istek yapabiliriz.

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