Fonctionnement

Introduction

L'API d'enregistrement sans contact aide les revendeurs d'appareils à automatiser leur intégration. Les outils commerciaux de votre organisation peuvent intégrer l'enregistrement sans contact, améliorant ainsi la productivité de vos utilisateurs et de vos clients. Aidez vos utilisateurs à:

  • Attribuez les appareils achetés au compte d'enregistrement sans contact d'un client.
  • Créer votre propre compte d'enregistrement sans contact
  • Associez le numéro de téléphone de votre organisation et les métadonnées de commande aux appareils.
  • Créer des rapports à propos des appareils affectés à vos clients

Ce document présente l'API et explique les motifs. Si vous souhaitez explorer l'API vous-même, consultez le guide de démarrage rapide pour Java, .NET ou Python.

Concepts de l'API

Les clients et les appareils sont les principales ressources que vous utilisez dans l'API. Pour créer des clients, appelez create. Vous pouvez créer des appareils à l'aide des méthodes de l'API de revendication (voir ci-dessous). Votre entreprise peut également créer des clients et des appareils à l'aide du portail d'enregistrement sans contact.

Relation entre l'appareil et le service client

Client
Entreprises auprès desquelles votre organisation vend des appareils. Les clients disposent d'un name et d'un ID. Faites appel à un client lorsque vous souhaitez revendiquer ou retrouver ses appareils. Pour en savoir plus, consultez Customer.
Appareil
Appareil Android ou ChromeOS compatible avec l'enregistrement sans contact que votre organisation vend à un client. Les appareils comportent des ID matériels, des métadonnées et des revendications des clients. Les appareils sont au cœur de l'API. Vous les utilisez donc dans presque toutes les méthodes. Pour en savoir plus, consultez Device.
DeviceIdentifier
Encapsule les ID matériels, tels que le code IMEI ou MEID, pour identifier un appareil fabriqué. Utilisez un DeviceIdentifier pour cibler l'appareil que vous souhaitez rechercher, mettre à jour ou revendiquer. Pour en savoir plus, consultez la section Identifiants.
DeviceMetadata
Stocke les paires clé/valeur des métadonnées de l'appareil. Utilisez DeviceMetadata pour stocker les métadonnées de votre organisation. Pour en savoir plus, consultez Métadonnées de l'appareil.

Pour répertorier toutes les méthodes et ressources d'API que votre application peut utiliser, consultez la documentation de référence de l'API.

Créer des clients

Pour les appareils Android, le revendeur est chargé de créer le compte client au nom de son client. Le client utilisera ce compte pour accéder au portail sans contact afin de configurer les paramètres de provisionnement de ses appareils. Cette opération n'est pas nécessaire pour les appareils ChromeOS qui disposent déjà d'un compte Google Workspace qu'ils utiliseront pour configurer leurs paramètres de provisionnement.

Vous pouvez appeler la méthode API create afin de créer des comptes client pour l'enregistrement sans contact. Étant donné que vos clients voient le nom de l'entreprise sur leur portail d'inscription sans contact, l'utilisateur de votre application doit confirmer qu'il est correct. Une fois le client créé, vous ne pouvez plus modifier son nom.

Vous devez inclure au moins une adresse e-mail professionnelle associée à un compte Google pour être le propriétaire. Vous ne pouvez pas utiliser de comptes Gmail personnels avec l'API. Si le client a besoin d'aide pour associer le compte, envoyez-lui les instructions de la page Associer un compte Google.

Une fois que vous avez créé un client en appelant l'API, il gère l'accès au portail de ses employés. Vous ne pouvez pas modifier les utilisateurs de vos clients à l'aide de l'API. L'extrait ci-dessous montre comment créer un client:

Java

// Provide the customer data as a Company type.
// The API requires a name and owners.
Company customer = new Company();
customer.setCompanyName("XYZ Corp");
customer.setOwnerEmails(Arrays.asList("liz@example.com", "darcy@example.com"));
customer.setAdminEmails(Collections.singletonList("jane@example.com"));

// Use our reseller ID for the parent resource name.
String parentResource = String.format("partners/%d", PARTNER_ID);

// Call the API to create the customer using the values in the company object.
CreateCustomerRequest body = new CreateCustomerRequest();
body.setCustomer(customer);
Company response = service.partners().customers().create(parentResource, body).execute();

.NET

// Provide the customer data as a Company type.
// The API requires a name and owners.
var customer = new Company
{
    CompanyName = "XYZ Corp",
    OwnerEmails = new String[] { "liz@example.com", "darcy@example.com" },
    AdminEmails = new String[] { "jane@example.com" }
};

// Use our reseller ID for the parent resource name.
var parentResource = String.Format("partners/{0}", PartnerId);

// Call the API to create the customer using the values in the company object.
var body = new CreateCustomerRequest
{
    Customer = customer
};
var request = service.Partners.Customers.Create(body, parentResource);
var response = request.Execute();

Python

# Provide the customer data as a Company type. The API requires
# a name and at least one owner.
company = {'companyName':'XYZ Corp', \
  'ownerEmails':['liz@example.com', 'darcy@example.com'], \
  'adminEmails':['jane@example.com']}

# Use our reseller ID for the parent resource name.
parent_resource = 'partners/{0}'.format(PARTNER_ID)

# Call the API to create the customer using the values in the company object.
response = service.partners().customers().create(parent=parent_resource,
    body={'customer':company}).execute()

Pour en savoir plus sur les rôles de propriétaire et d'administrateur pour les employés de votre client, consultez la page Utilisateurs du portail.

Revendiquer des appareils pour vos clients

Une fois que vos clients ont acheté des appareils, ils doivent configurer les paramètres de provisionnement pour ces appareils dans leur compte. Revendiquer un appareil permet de l'ajouter à l'enregistrement sans contact et de permettre au client de configurer les paramètres de provisionnement.

L'enregistrement de provisionnement d'un appareil contient une section pour l'enregistrement sans contact. Pour attribuer l'appareil, revendiquez la section d'enregistrement sans contact de l'enregistrement pour un client. Appelez les méthodes partners.devices.claim ou partners.devices.claimAsync avec le client comme argument. Indiquez toujours SECTION_TYPE_ZERO_TOUCH comme valeur pour sectionType.

Vous devez annuler la revendication de l'appareil d'un client (voir ci-dessous) avant de pouvoir en revendiquer un autre. Les méthodes de revendication validate les champs DeviceIdentifier, y compris le code IMEI ou MEID, ou le numéro de série, le nom du fabricant et le modèle, ainsi que l'ID d'appareil certifié pour les appareils ChromeOS, lors de la création d'un appareil.

L'extrait de code ci-dessous montre comment revendiquer un appareil:

Java

// Identify the device to claim.
DeviceIdentifier identifier = new DeviceIdentifier();
// The manufacturer value is optional but recommended for cellular devices
identifier.setManufacturer("Google");
identifier.setImei("098765432109875");

// Create the body to connect the customer with the device.
ClaimDeviceRequest body = new ClaimDeviceRequest();
body.setDeviceIdentifier(identifier);
body.setCustomerId(customerId);
body.setSectionType("SECTION_TYPE_ZERO_TOUCH");

// Claim the device.
ClaimDeviceResponse response = service.partners().devices().claim(PARTNER_ID, body).execute();

.NET

// Identify the device to claim.
var deviceIdentifier = new DeviceIdentifier
{
    // The manufacturer value is optional but recommended for cellular devices
    Manufacturer = "Google",
    Imei = "098765432109875"
};

// Create the body to connect the customer with the device.
ClaimDeviceRequest body = new ClaimDeviceRequest
{
    DeviceIdentifier = deviceIdentifier,
    CustomerId = CustomerId,
    SectionType = "SECTION_TYPE_ZERO_TOUCH"
};

// Claim the device.
var response = service.Partners.Devices.Claim(body, PartnerId).Execute();

Python

# Identify the device to claim.
# The manufacturer value is optional but recommended for cellular devices
device_identifier = {'manufacturer':'Google', 'imei':'098765432109875'}

# Create the body to connect the customer with the device.
request_body = {'deviceIdentifier':device_identifier, \
    'customerId':customer_id, \
    'sectionType':'SECTION_TYPE_ZERO_TOUCH'}

# Claim the device.
response = service.partners().devices().claim(partnerId=PARTNER_ID,
    body=request_body).execute()

Annulation de la revendication d'appareils

Votre organisation peut annuler la revendication d'un appareil auprès d'un client. Le fait de retirer un appareil le supprime de l'enregistrement sans contact. Un revendeur peut retirer la revendication d'un appareil qu'il souhaite migrer vers un autre compte, qu'il doit retourner ou qui a été revendiqué par erreur. Appelez la méthode partners.devices.unclaim ou partners.devices.unclaimAsync pour retirer un appareil d'un client.

Fournisseurs

Vous pouvez faire appel à des fournisseurs pour représenter les partenaires revendeurs de votre réseau de revendeurs, des opérateurs locaux au sein d'un réseau de revendeurs mondial ou toute organisation qui vend des appareils en votre nom. Les fournisseurs vous aident à séparer vos utilisateurs, clients et appareils:

  • Les fournisseurs que vous créez ne peuvent pas voir votre compte d'enregistrement sans contact ni les comptes des autres.
  • Vous pouvez afficher les clients et les appareils de vos fournisseurs, et vous pouvez annuler l'enregistrement de leurs appareils. Toutefois, vous ne pouvez pas attribuer d'appareils aux clients de vos fournisseurs.

Utilisez le portail pour créer des fournisseurs pour votre organisation. Vous ne pouvez pas utiliser l'API. Pour créer un fournisseur, vous devez avoir le rôle Propriétaire. Si votre organisation comporte des fournisseurs, vous pouvez appeler partners.vendors.list pour les lister et partners.vendors.customers.list pour obtenir les clients de votre fournisseur. L'exemple suivant utilise ces deux méthodes pour imprimer un rapport indiquant l'état des conditions d'utilisation pour les clients des fournisseurs:

Java

// First, get the organization's vendors.
String parentResource = String.format("partners/%d", PARTNER_ID);
ListVendorsResponse results = service.partners().vendors().list(parentResource).execute();
if (results.getVendors() == null) {
  return;
}

// For each vendor, report the company name and a maximum 5 customers.
for (Company vendor: results.getVendors()) {
  System.out.format("\n%s customers\n", vendor.getCompanyName());
  System.out.println("---");
  // Use the vendor's API resource name as the parent resource.
  AndroidProvisioningPartner.Partners.Vendors.Customers.List customerRequest =
      service.partners().vendors().customers().list(vendor.getName());
  customerRequest.setPageSize(5);
  ListVendorCustomersResponse customerResponse = customerRequest.execute();

  List<Company> customers = customerResponse.getCustomers();
  if (customers == null) {
    System.out.println("No customers");
    break;
  } else {
    for (Company customer: customers) {
      System.out.format("%s: %s\n",
          customer.getCompanyName(),
          customer.getTermsStatus());
    }
  }
}

.NET

// First, get the organization's vendors.
var parentResource = String.Format("partners/{0}", PartnerId);
var results = service.Partners.Vendors.List(parentResource).Execute();
if (results.Vendors == null)
{
    return;
}

// For each vendor, report the company name and a maximum 5 customers.
foreach (Company vendor in results.Vendors)
{
    Console.WriteLine("\n{0} customers", vendor);
    Console.WriteLine("---");
    // Use the vendor's API resource name as the parent resource.
    PartnersResource.VendorsResource.CustomersResource.ListRequest customerRequest =
        service.Partners.Vendors.Customers.List(vendor.Name);
    customerRequest.PageSize = 5;
    var customerResponse = customerRequest.Execute();

    IList<Company> customers = customerResponse.Customers;
    if (customers == null)
    {
        Console.WriteLine("No customers");
        break;
    }
    else
    {
        foreach (Company customer in customers)
        {
            Console.WriteLine("{0}: {1}", customer.Name, customer.TermsStatus);
        }
    }
}

Python

# First, get the organization's vendors.
parent_resource = 'partners/{0}'.format(PARTNER_ID)
vendor_response = service.partners().vendors().list(
    parent=parent_resource).execute()
if 'vendors' not in vendor_response:
  return

# For each vendor, report the company name and a maximum 5 customers.
for vendor in vendor_response['vendors']:
  print '\n{0} customers'.format(vendor['companyName'])
  print '---'
  # Use the vendor's API resource name as the parent resource.
  customer_response = service.partners().vendors().customers().list(
      parent=vendor['name'], pageSize=5).execute()
  if 'customers' not in customer_response:
    print 'No customers'
    break
  for customer in customer_response['customers']:
    print '  {0}: {1}'.format(customer['name'], customer['termsStatus'])

Si vous possédez une collection d'appareils, vous devrez peut-être savoir quel revendeur ou fournisseur a revendiqué l'appareil. Pour obtenir l'ID revendeur numérique, examinez la valeur du champ resellerId dans l'enregistrement de revendication d'un appareil.

Votre organisation peut retirer la revendication d'un appareil revendiqué par un fournisseur. Pour les autres appels d'API qui modifient les appareils, vous devez vérifier que votre organisation a revendiqué l'appareil avant d'appeler la méthode API. L'exemple suivant montre comment procéder:

Java

// Get the devices claimed for two customers: one of our organization's
// customers and one of our vendor's customers.
FindDevicesByOwnerRequest body = new FindDevicesByOwnerRequest();
body.setSectionType("SECTION_TYPE_ZERO_TOUCH");
body.setCustomerId(Arrays.asList(resellerCustomerId, vendorCustomerId));
body.setLimit(MAX_PAGE_SIZE);
FindDevicesByOwnerResponse response =
    service.partners().devices().findByOwner(PARTNER_ID, body).execute();
if (response.getDevices() == null) {
  return;
}

for (Device device: response.getDevices()) {
  // Confirm the device was claimed by our reseller and not a vendor before
  // updating metadata in another method.
  for (DeviceClaim claim: device.getClaims()) {
    if (claim.getResellerId() == PARTNER_ID) {
      updateDeviceMetadata(device.getDeviceId());
      break;
    }
  }
}

.NET

// Get the devices claimed for two customers: one of our organization's
// customers and one of our vendor's customers.
FindDevicesByOwnerRequest body = new FindDevicesByOwnerRequest
{
    Limit = MaxPageSize,
    SectionType = "SECTION_TYPE_ZERO_TOUCH",
    CustomerId = new List<long?>
    {
        resellerCustomerId,
        vendorCustomerId
    }
};
var response = service.Partners.Devices.FindByOwner(body, PartnerId).Execute();
if (response.Devices == null)
{
    return;
}

foreach (Device device in response.Devices)
{
    // Confirm the device was claimed by our reseller and not a vendor before
    // updating metadata in another method.
    foreach (DeviceClaim claim in device.Claims)
    {
        if (claim.ResellerId == PartnerId)
        {
            UpdateDeviceMetadata(device.DeviceId);
            break;
        }
    }
}

Python

# Get the devices claimed for two customers: one of our organization's
# customers and one of our vendor's customers.
request_body = {'limit':MAX_PAGE_SIZE, \
  'pageToken':None, \
  'customerId':[reseller_customer_id, vendor_customer_id], \
  'sectionType':'SECTION_TYPE_ZERO_TOUCH'}
response = service.partners().devices().findByOwner(partnerId=PARTNER_ID,
    body=request_body).execute()

for device in response['devices']:
  # Confirm the device was claimed by our reseller and not a vendor before
  # updating metadata in another method.
  for claim in device['claims']:
    if claim['resellerId'] == PARTNER_ID:
      update_device_metadata(device['deviceId'])
      break

Opérations par lot de longue durée

L'API inclut des versions asynchrones des méthodes de l'appareil. Ces méthodes permettent le traitement par lot de nombreux appareils, tandis que les méthodes synchrones traitent un appareil pour chaque requête API. Les noms des méthodes asynchrones comportent un suffixe Async, par exemple claimAsync.

Les méthodes d'API asynchrones renvoient un résultat avant la fin du traitement. Les méthodes asynchrones aident également votre application (ou votre outil) à rester réactive pour vos utilisateurs en attendant la fin d'une opération de longue durée. Votre application doit vérifier régulièrement l'état de l'opération.

Opérations

Vous pouvez suivre une opération par lot de longue durée à l'aide d'un Operation. Un appel réussi à une méthode asynchrone renvoie une référence à l'opération dans la réponse. L'extrait de code JSON ci-dessous montre une réponse typique après l'appel de updateMetadataAsync:

{
  "name": "operations/apibatchoperation/1234567890123476789"
}

Chaque opération contient une liste de tâches individuelles. Appelez operations.get pour obtenir des informations sur l'état et les résultats des tâches contenues dans l'opération. L'extrait ci-dessous vous indique comment procéder. Dans votre propre application, vous devrez gérer toutes les erreurs.

Java

// Build out the request body to apply the same order number to a customer's
// purchase of 2 devices.
UpdateMetadataArguments firstUpdate = new UpdateMetadataArguments();
firstUpdate.setDeviceMetadata(metadata);
firstUpdate.setDeviceId(firstTargetDeviceId);

UpdateMetadataArguments secondUpdate = new UpdateMetadataArguments();
secondUpdate.setDeviceMetadata(metadata);
secondUpdate.setDeviceId(firstTargetDeviceId);

// Start the device metadata update.
UpdateDeviceMetadataInBatchRequest body = new UpdateDeviceMetadataInBatchRequest();
body.setUpdates(Arrays.asList(firstUpdate, secondUpdate));
Operation response = service
    .partners()
    .devices()
    .updateMetadataAsync(PARTNER_ID, body)
    .execute();

// Assume the metadata update started, so get the Operation for the update.
Operation operation = service.operations().get(response.getName()).execute();

.NET

// Build out the request body to apply the same order number to a customer's
// purchase of 2 devices.
var updates = new List<UpdateMetadataArguments>
{
    new UpdateMetadataArguments
    {
        DeviceMetadata = metadata,
        DeviceId = firstTargetDeviceId
    },
    new UpdateMetadataArguments
    {
        DeviceMetadata = metadata,
        DeviceId = secondTargetDeviceId
    }
};

// Start the device metadata update.
UpdateDeviceMetadataInBatchRequest body = new UpdateDeviceMetadataInBatchRequest
{
    Updates = updates
};
var response = service.Partners.Devices.UpdateMetadataAsync(body, PartnerId).Execute();

// Assume the metadata update started, so get the Operation for the update.
Operation operation = service.Operations.Get(response.Name).Execute();

Python

# Build out the request body to apply the same order number to a customer's
# purchase of 2 devices.
updates = [{'deviceMetadata':metadata,'deviceId':first_target_device_id},
    {'deviceMetadata':metadata,'deviceId':second_target_device_id}]

# Start the device metadata update.
response = service.partners().devices().updateMetadataAsync(
    partnerId=PARTNER_ID, body={'updates':updates}).execute()

# Assume the metadata update started, so get the Operation for the update.
operation = service.operations().get(name=response['name']).execute()

Pour savoir si une opération s'est terminée, recherchez un champ done avec la valeur true. Si done est manquant ou si false, l'opération est toujours en cours d'exécution.

Réponses

Une fois l'opération terminée, l'API la met à jour avec le résultat, même si toutes les tâches ou aucune des tâches individuelles aboutissent. Le champ response est un objet DevicesLongRunningOperationResponse qui détaille le traitement de chaque appareil au cours de l'opération.

Inspectez le champ successCount pour déterminer efficacement si des tâches ont échoué et éviter les itérations via de longues listes de résultats. Le champ perDeviceStatus de DevicesLongRunningOperationResponse est une liste d'instances OperationPerDevice qui détaillent chaque appareil concerné par l'opération. L'ordre de la liste correspond aux tâches de la requête d'origine.

Chaque tâche OperationPerDevice contient un champ result et un résumé de la requête reçue par le serveur. Vérifiez si la tâche a réussi ou échoué à l'aide du champ result.

L'extrait de code JSON ci-dessous montre une partie d'une réponse type d'une opération après un appel à updateMetadataAsync:

"response": {
  "perDeviceStatus": [
    {
      "result": {
        "deviceId": "12345678901234567",
        "status": "SINGLE_DEVICE_STATUS_SUCCESS"
      },
      "updateMetadata": {
        "deviceId": "12345678901234567",
        "deviceMetadata": {
          "entries": {
            "phonenumber": "+1 (800) 555-0100"
          }
        }
      }
    }
  ],
  "successCount": 1
}

Suivre vos progrès

Si votre application doit suivre la progression, vous devez récupérer régulièrement l'opération. Le champ metadata contient une instance DevicesLongRunningOperationMetadata qui permet à votre application de vérifier la dernière progression d'une opération en cours d'exécution. Utilisez les champs de DevicesLongRunningOperationMetadata répertoriés dans le tableau suivant pour suivre la progression de l'opération:

Champ Utilisation type
processingStatus Passage de BATCH_PROCESS_PENDING à BATCH_PROCESS_IN_PROGRESS, puis à BATCH_PROCESS_PROCESSED au fur et à mesure de la progression de l'opération.
progress Pourcentage de mises à jour traitées. Votre application peut s'en servir pour estimer un temps de fin. Étant donné que la valeur progress peut être 100 pendant la fin de l'opération, vérifiez le champ done d'une opération pour savoir si elle s'est terminée et a un résultat.
devicesCount Affiche le nombre de mises à jour en cours d'opération. Ce nombre peut être différent du nombre de mises à jour incluses dans votre requête si l'API ne peut pas analyser certaines des mises à jour.

L'exemple simplifié ci-dessous montre comment une application peut utiliser les métadonnées de progression pour définir des intervalles d'interrogation. Dans votre application, vous aurez peut-être besoin d'un exécuteur de tâches plus sophistiqué pour l'interrogation. Vous devez également ajouter une fonctionnalité de gestion des erreurs.

Java

// Milliseconds between polling the API.
private static long MIN_INTERVAL = 2000;
private static long MAX_INTERVAL = 10000;

// ...
// Start the device metadata update.
Operation response = service
    .partners()
    .devices()
    .updateMetadataAsync(PARTNER_ID, body)
    .execute();
String operationName = response.getName();

// Start polling for completion.
long startTime = new Date().getTime();
while (true) {

  // Get the latest update on the operation's progress using the API.
  Operation operation = service.operations().get(operationName).execute();

  if (operation.get("done") != null && operation.getDone()) {
    // The operation is finished. Print the status.
    System.out.format("Operation complete: %s of %s successful device updates\n",
        operation.getResponse().get("successCount"),
        operation.getMetadata().get("devicesCount"));
    break;

  } else {
    // Estimate how long the operation *should* take - within min and max value.
    BigDecimal opProgress = (BigDecimal) operation.getMetadata().get("progress");
    double progress = opProgress.longValue();
    long interval = MAX_INTERVAL;
    if (progress > 0) {
      interval = (long) ((new Date().getTime() - startTime) *
          ((100.0 - progress) / progress));
    }
    interval = Math.max(MIN_INTERVAL, Math.min(interval, MAX_INTERVAL));

    // Sleep until the operation should be complete.
    Thread.sleep(interval);
  }
}

.NET

// Milliseconds between polling the API.
private static double MinInterval = 2000;
private static double MaxInterval = 10000;

// ...
// Start the device metadata update.
var response = service.Partners.Devices.UpdateMetadataAsync(body, PartnerId).Execute();
var operationName = response.Name;

// Start polling for completion.
var startTime = DateTime.Now;
while (true)
{

    // Get the latest update on the operation's progress using the API.
    Operation operation = service.Operations.Get(operationName).Execute();

    if (operation.Done == true)
    {
        // The operation is finished. Print the status.
        Console.WriteLine("Operation complete: {0} of {1} successful device updates",
                          operation.Response["successCount"],
                          operation.Metadata["devicesCount"]);
        break;
    }
    else
    {
        // Estimate how long the operation *should* take - within min and max value.
        double progress = (double)(long)operation.Metadata["progress"];
        double interval = MaxInterval;
        if (progress > 0)
        {
            interval = DateTime.Now.Subtract(startTime).TotalMilliseconds *
                                     ((100.0 - progress) / progress);
        }
        interval = Math.Max(MinInterval, Math.Min(interval, MaxInterval));

        // Sleep until the operation should be complete.
        System.Threading.Thread.Sleep((int)interval);
    }
}

Python

# Seconds between polling the API.
MIN_INTERVAL = 2;
MAX_INTERVAL = 10;

# ...
# Start the device metadata update
response = service.partners().devices().updateMetadataAsync(
  partnerId=PARTNER_ID, body={'updates':updates}).execute()

op_name = response['name']
start_time = time.time()

# Start polling for completion
while True:
  # Get the latest update on the operation's progress using the API
  op = service.operations().get(name=op_name).execute()

  if 'done' in op and op['done']:
    # The operation is finished. Print the status.
    print('Operation complete: {0} of {1} successful device updates'.format(
      op['response']['successCount'], op['metadata']['devicesCount']
    ))
    break
  else:
    # Estimate how long the operation *should* take - within min and max.
    progress = op['metadata']['progress']
    interval = MIN_INTERVAL
    if progress > 0:
      interval = (time.time() - start_time) * ((100.0 - progress) / progress)
    interval = max(MIN_INTERVAL, min(interval, MAX_INTERVAL))

    # Sleep until the operation should be complete.
    time.sleep(interval)

Choisissez une approche de sondage pertinente pour les utilisateurs de votre application. Certains utilisateurs de l'application peuvent bénéficier de mises à jour régulières de l'avancement s'ils attendent la fin d'un processus.

Résultats paginés

La méthode API partners.devices.findByOwner peut renvoyer des listes d'appareils très volumineuses. Pour réduire la taille des réponses, cette méthode et d'autres méthodes d'API (telles que partners.devices.findByIdentifier) sont compatibles avec les résultats paginés. Avec les résultats paginés, votre application peut demander et traiter de grandes listes de manière itérative, page par page.

Après avoir appelé la méthode API, vérifiez si la réponse inclut une valeur pour nextPageToken. Si nextPageToken n'est pas null, votre application peut l'utiliser pour récupérer une autre page d'appareils en appelant à nouveau la méthode. Vous devez définir une limite supérieure pour le nombre d'appareils dans le paramètre limit. Si nextPageToken est défini sur null, votre application a demandé la dernière page.

L'exemple de méthode ci-dessous montre comment votre application peut imprimer une liste d'appareils, page par page:

Java

private static long MAX_PAGE_SIZE = 10;

// ...
/**
 * Demonstrates how to loop through paginated lists of devices.
 * @param pageToken       The token specifying which result page to return.
 * @throws IOException    If the zero-touch API call fails.
 */
private void printDevices(String pageToken) throws IOException {

  // Create the request body to find the customer's devices.
  FindDevicesByOwnerRequest body = new FindDevicesByOwnerRequest();
  body.setLimit(MAX_PAGE_SIZE);
  body.setSectionType("SECTION_TYPE_ZERO_TOUCH");
  body.setCustomerId(Collections.singletonList(targetCustomerId));

  // Call the API to get a page of Devices. Send a page token from the method
  // argument (might be None). If the page token is None, the API returns the first page.
  FindDevicesByOwnerResponse response =
      service.partners().devices().findByOwner(PARTNER_ID, body).execute();
  if (response.getDevices() == null) {
    return;
  }

  // Print the devices included in this page of results.
  for (Device device: response.getDevices()) {
    System.out.format("Device %s\n", device.getName());
  }
  System.out.println("---");

  // Check to see if another page of devices is available. If yes,
  // fetch and print the devices.
  if (response.getNextPageToken() != null) {
    this.printDevices(response.getNextPageToken());
  }
}

// ...
// Pass null to start printing the first page of devices.
printDevices(null);

.NET

private static int MaxPageSize = 10;

// ...
/// <summary>Demonstrates how to loop through paginated lists of devices.</summary>
/// <param name="pageToken">The token specifying which result page to return.</param>
private void PrintDevices(string pageToken)
{
    // Create the request body to find the customer's devices.
    FindDevicesByOwnerRequest body = new FindDevicesByOwnerRequest
    {
        PageToken = pageToken,
        Limit = MaxPageSize,
        SectionType = "SECTION_TYPE_ZERO_TOUCH",
        CustomerId = new List<long?>
        {
            targetCustomerId
        }
    };

    // Call the API to get a page of Devices. Send a page token from the method
    // argument (might be None). If the page token is None, the API returns the first page.
    var response = service.Partners.Devices.FindByOwner(body, PartnerId).Execute();
    if (response.Devices == null)
    {
        return;
    }

    // Print the devices included in this page of results.
    foreach (Device device in response.Devices)
    {
        Console.WriteLine("Device: {0}", device.Name);
    }
    Console.WriteLine("---");

    // Check to see if another page of devices is available. If yes,
    // fetch and print the devices.
    if (response.NextPageToken != null)
    {
        this.PrintDevices(response.NextPageToken);
    }
}

// ...
// Pass null to start printing the first page of devices.
PrintDevices(null);

Python

MAX_PAGE_SIZE = 10;

# ...
def print_devices(page_token):
  """Demonstrates how to loop through paginated lists of devices.

  Args:
    page_token: The token specifying which result page to return.
  """

   # Create the body to find the customer's devices.
  request_body = {'limit':MAX_PAGE_SIZE, \
    'pageToken':page_token, \
    'customerId':[target_customer_id], \
    'sectionType':'SECTION_TYPE_ZERO_TOUCH'}

  # Call the API to get a page of Devices. Send a page token from the method
  # argument (might be None). If the page token is None,
  # the API returns the first page.
  response = service.partners().devices().findByOwner(partnerId=PARTNER_ID,
    body=request_body).execute()

  # Print the devices included in this page of results.
  for device in response['devices']:
    print 'Device: {0}'.format(device['name'])
  print '---'

  # Check to see if another page of devices is available. If yes,
  # fetch and print the devices.
  if 'nextPageToken' in response:
    print_devices(response['nextPageToken'])

# ...
# Pass None to start printing the first page of devices.
print_devices(None);

Étapes suivantes

Maintenant que vous savez comment fonctionne l'API, essayez les exemples avec un guide de démarrage rapide pour Java, .NET ou Python.