איך זה עובד

מבוא

ממשק ה-API להרשמה דרך הארגון עוזר למפיצים של מכשירים להפוך את השילוב שלהם לאוטומטי. באמצעות כלי המכירות בארגון תוכלו להירשם דרך הארגון, וכך להפוך את המשתמשים ואת הלקוחות שלכם לפרודוקטיביים יותר. השתמשו ב-API כדי לעזור למשתמשים:

  • יש להקצות מכשירים שנרכשו לחשבון הרישום דרך הארגון של הלקוח.
  • יוצרים חשבון להרשמה דרך הארגון של הלקוח.
  • אפשר לצרף למכשירים את מספר הטלפון והמטא-נתונים של ההזמנה של הארגון.
  • יצירת דוחות על מכשירים שהוקצו ללקוחות שלך.

מסמך זה מציג את ה-API ומסביר את הדפוסים. אם אתם רוצים להתעמק ב-API בעצמכם, תוכלו להיעזר במדריך למתחילים ל-Java, NET. או Python.

מושגים ב-API

לקוחות ומכשירים הם משאבי הליבה שבהם אתם משתמשים ב-API. כדי ליצור לקוחות, צריך להתקשר אל create. אתם יכולים ליצור מכשירים באמצעות שיטות של הצהרת בעלות API (ראו בהמשך). הארגון שלכם יכול גם ליצור לקוחות ומכשירים באמצעות פורטל ההרשמה דרך הארגון.

הקשר בין המכשיר למשאב הלקוח

לקוח/ה
חברות שהארגון שלך מוכר מכשירים שלהן. ללקוחות יש name וגם ID. משתמשים בלקוח כשרוצים לתבוע בעלות על המכשירים שלו או לאתר אותו. למידע נוסף: Customer.
מכשיר
מכשיר Android או ChromeOS שאפשר להירשם דרך הארגון, אם הארגון מוכר ללקוחות. למכשירים יש מזהי חומרה, מטא-נתונים ותביעות של לקוחות. מכשירים הם אמצעי מרכזי ב-API, כך שאתם משתמשים בהם כמעט בכל השיטות. מידע נוסף זמין כאן: Device.
DeviceIdentifier
כולל מזהי חומרה, כמו IMEI או MEID, כדי לזהות מכשיר שיוצר. השתמשו ב-DeviceIdentifier כדי לטרגט את המכשיר שאתם רוצים לאתר, לעדכן או לתבוע עליו בעלות. למידע נוסף קראו את המאמר מזהים.
DeviceMetadata
שמירת צמדי מפתח/ערך של מטא-נתונים למכשיר. שימוש ב-DeviceMetadata כדי לאחסן את המטא-נתונים של הארגון. למידע נוסף, מומלץ לקרוא את המאמר מטא-נתונים של המכשיר.

כדי לראות רשימה של כל שיטות ה-API והמשאבים שבהם האפליקציה יכולה להשתמש, עיינו בחומר העזר בנושא API.

יצירת לקוחות

במכשירי Android, המפיץ אחראי ליצור את חשבון הלקוח בשם הלקוח. הלקוח ישתמש בחשבון הזה כדי לגשת לפורטל ללא מגע לצורך קביעת ההגדרות להקצאת הרשאות ידנית במכשירים. לא צריך לבצע את האימות במכשירי ChromeOS שכבר יש להם חשבון Google Workspace, והם ישתמשו בו כדי לקבוע את הגדרות ניהול ההקצאות.

אפשר לבצע קריאה לשיטת ה-API create כדי ליצור חשבונות לקוח להרשמה דרך הארגון. מאחר שהלקוחות שלכם רואים את שם החברה בפורטל ההרשמה דרך הארגון, המשתמשים באפליקציה צריכים לאשר שהיא נכונה. אי אפשר לערוך שם של לקוח אחרי שיצרתם אותו.

כדי להיות הבעלים, עליכם לכלול לפחות כתובת אימייל אחת של החברה, המשויכת לחשבון Google. לא ניתן להשתמש בחשבונות Gmail אישיים עם ה-API. אם הלקוח צריך עזרה בשיוך החשבון, תוכלו לשלוח את ההוראות בקטע שיוך חשבון Google.

אחרי שיוצרים לקוח באמצעות קריאה ל-API, הוא מנהל את הגישה לפורטל של העובדים – אי אפשר לערוך את המשתמשים של הלקוחות באמצעות ה-API. קטע הקוד הבא מראה איך אפשר ליצור לקוח:

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

למידע נוסף על תפקידי הבעלים והאדמין של העובדים של הלקוח, קראו את המאמר משתמשי פורטל.

תביעת בעלות על מכשירים עבור לקוחות

אחרי שהלקוחות ירכשו מכשירים, הם ירצו לקבוע את הגדרות ניהול ההקצאות למכשירים האלה בחשבון שלהם. תביעת בעלות על מכשיר מוסיפה את המכשיר להרשמה דרך הארגון, ומאפשרת ללקוח לקבוע את הגדרות ניהול ההקצאות.

רשומת ניהול ההקצאות של מכשיר כוללת קטע להרשמה דרך הארגון. כדי להקצות את המכשיר ללקוח, צריך לממש את קטע הרישום מתוך הרשומה עבור הלקוח. מפעילים את השיטה partners.devices.claim או partners.devices.claimAsync כארגומנט של הלקוח. צריך תמיד לציין את SECTION_TYPE_ZERO_TOUCH כערך של sectionType.

לפני שתוכלו לתבוע בעלות על אותו מכשיר עבור לקוח אחר, עליכם לבטל את תביעת הבעלות (ראו בהמשך). כשיוצרים מכשיר חדש, שיטות תביעת הבעלות validate את השדות DeviceIdentifier, כולל מספר ה-IMEI או ה-MEID, המספר הסידורי, שם היצרן והדגם, ומזהה המכשיר המאומת של מכשירי ChromeOS.

קטע הקוד הבא מראה איך לתבוע בעלות על מכשיר:

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

המערכת מסירה את הבעלות על המכשירים

הארגון שלך יכול לבטל את תביעת הלקוח על מכשיר. ביטול תביעת בעלות על מכשיר מסיר אותו מההרשמה דרך הארגון. מפיץ עשוי לבטל תביעת בעלות על מכשיר שהוא רוצה להעביר לחשבון אחר, להחזיר אותו או שנתבעה עליו בעלות בטעות. מפעילים את השיטה partners.devices.unclaim או את השיטה partners.devices.unclaimAsync כדי לבטל את הבעלות על המכשיר מהלקוח.

ספקים

אפשר להיעזר בספקים כדי לייצג שותפים של מפיצים ברשת סוכנויות הרכב, מפעילים מקומיים ברשת מפיצים גלובלית או כל ארגון שמוכר מכשירים בשמכם. ספקים עוזרים להפריד בין המשתמשים, הלקוחות והמכשירים:

  • הספקים שתיצרו לא יוכלו לראות את חשבון ההרשמה דרך הארגון או את החשבונות אחד של השני.
  • אפשר לראות את הלקוחות והמכשירים של הספקים ולבטל את הרישום של המכשירים של הספקים. אבל אי אפשר להקצות מכשירים ללקוחות של הספקים.

בפורטל תוכלו ליצור ספקים לארגון – אי אפשר להשתמש ב-API. כדי ליצור ספק חדש, התפקיד בחשבון שלכם צריך להיות בעלים. אם בארגון יש ספקים, אפשר להתקשר אל partners.vendors.list כדי להציג את רשימת הספקים ו-partners.vendors.customers.list כדי למשוך אליו את הלקוחות. בדוגמה הבאה נשתמש בשתי השיטות האלה כדי להדפיס דוח של סטטוס התנאים וההגבלות ללקוחות של הספקים:

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'])

אם יש לכם אוסף של מכשירים, יכול להיות שתצטרכו לדעת איזה מפיץ או ספק תבע בעלות על המכשיר. כדי למצוא את מזהה המפיץ המספרי, צריך לבדוק את הערך בשדה resellerId ברשומת התביעה של המכשיר.

הארגון שלך יכול לבטל את תביעת הבעלות על מכשיר שנתבע על ידי הספק. לגבי קריאות אחרות ל-API שמשנות מכשירים, עליכם לוודא שהארגון תבע בעלות על המכשיר לפני שאתם מפעילים את שיטת ה-API. הדוגמה הבאה מראה איך אפשר לעשות את זה:

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

פעולות ממושכות באצווה

ה-API כולל גרסאות אסינכרוניות של שיטות המכשיר. בעזרת השיטות האלה אפשר לעבד באצווה מכשירים רבים, בעוד שהשיטות הסינכרוניות מעבדות מכשיר אחד לכל בקשת API. לשמות של השיטות האסינכרוניות יש סיומת Async, למשל claimAsync.

שיטות API אסינכרוניות מחזירות תוצאה לפני שהעיבוד הושלם. שיטות אסינכרוניות גם עוזרות לאפליקציה (או לכלי) להמשיך להגיב למשתמשים בזמן שהם ממתינים להשלמת פעולה ממושכת. מדי פעם האפליקציה צריכה לבדוק את סטטוס הפעולה.

פעולות

משתמשים ב-Operation כדי לעקוב אחר פעולות ממושכות באצווה. קריאה מוצלחת לשיטה אסינכרונית מחזירה בתגובה הפניה לפעולה. קטע ה-JSON הבא מציג תגובה אופיינית לאחר ביצוע קריאה ל-updateMetadataAsync:

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

כל פעולה מכילה רשימה של משימות נפרדות. אפשר להתקשר אל operations.get כדי לברר מה הסטטוס והתוצאות של המשימות שנכללות בפעולה. קטע הקוד הבא מראה איך אפשר לעשות את זה. עליך לטפל בשגיאות באפליקציה שלך.

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

כדי לבדוק אם פעולה מסוימת הסתיימה, צריך לבדוק את הפעולה בשדה done עם הערך true. אם השדה done חסר או הערך false, הפעולה עדיין מתבצעת.

תשובות

אחרי שהפעולה מסתיימת, ה-API מעדכן אותה עם התוצאה – גם אם כל המשימות הנפרדות או אף אחת מהן לא בוצעו בהצלחה. השדה response הוא אובייקט DevicesLongRunningOperationResponse שבו מפורט העיבוד של כל מכשיר בפעולה.

בודקים את השדה successCount כדי לראות ביעילות אם משימות נכשלו וכדי להימנע מחזרה על רשימות גדולות של תוצאות. השדה perDeviceStatus של DevicesLongRunningOperationResponse הוא רשימה של מכונות OperationPerDevice שמפורטות בהן כל המכשירים בפעולה. סדר הרשימות תואם למשימות בבקשה המקורית.

כל משימת OperationPerDevice מכילה את השדה result וסיכום תזכורת לגבי הבקשה שהתקבלה בשרת. בשדה result בודקים אם המשימה הצליחה או נכשלה.

קטע הקוד של ה-JSON שמוצג כאן הוא חלק מתגובה אופיינית מפעולה אחרי קריאה ל-updateMetadataAsync:

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

מעקב אחר ההתקדמות

אם אתם צריכים לעקוב אחרי ההתקדמות באפליקציה, תצטרכו לבצע אחזור מחדש מדי פעם. השדה metadata מכיל מופע של DevicesLongRunningOperationMetadata שעוזר לאפליקציה לבדוק את ההתקדמות האחרונה של פעולה פועלת. משתמשים בשדות של DevicesLongRunningOperationMetadata שמפורטים בטבלה הבאה כדי לעקוב אחרי התקדמות הפעולה:

שדה שימוש רגיל
processingStatus שינויים מ-BATCH_PROCESS_PENDING ל-BATCH_PROCESS_IN_PROGRESS, ולאחר מכן ל-BATCH_PROCESS_PROCESSED עם התקדמות הפעולה.
progress אחוז העדכונים שעובדו. האפליקציה יכולה להשתמש בערך הזה כדי להעריך את זמן הסיום. מכיוון שהערך progress יכול להיות 100 בזמן שהפעולה מסתיימת, כדאי לבדוק את השדה done של הפעולה כדי לדעת אם היא הסתיימה ויש לה תוצאה.
devicesCount הצגת מספר העדכונים בפעולה. אם ה-API לא יכול לנתח חלק מהעדכונים, יכול להיות שהמספר הזה יהיה שונה ממספר העדכונים בבקשה.

הדוגמה הבאה מראה איך אפליקציה יכולה להשתמש במטא-נתונים של ההתקדמות כדי להגדיר מרווחי סקרים. יכול להיות שבאפליקציה תצטרכו גרסה מתוחכמת יותר של הרצת משימות לביצוע סקרים. תצטרכו גם להוסיף טיפול בשגיאות.

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)

צריך לבחור שיטת סקרים שמתאימה למשתמשי האפליקציה. חלק ממשתמשי האפליקציה יכולים להפיק תועלת מעדכוני התקדמות שוטפים אם הם ממתינים להשלמת תהליך.

תוצאות בדפים

שיטת ה-API partners.devices.findByOwner עשויה להחזיר רשימות ארוכות מאוד של מכשירים. כדי להקטין את גודל התשובה, השיטה הזו ושיטות API אחרות (כמו partners.devices.findByIdentifier) תומכות בתוצאות לדפים. בעזרת התוצאות של חלוקה לדפים, האפליקציה יכולה לבקש ולעבד רשימות גדולות באופן חזרתי, בכל דף בנפרד.

אחרי שמפעילים את שיטת ה-API, צריך לבדוק אם התשובה כוללת ערך של nextPageToken. אם nextPageToken הוא לא הערך null, האפליקציה יכולה להשתמש בו כדי לאחזר דף נוסף של מכשירים על ידי קריאה חוזרת לשיטה. צריך להגדיר תקרה למספר המכשירים בפרמטר limit. אם הערך של nextPageToken הוא null, אז האפליקציה שלכם ביקשה את הדף האחרון.

השיטה לדוגמה למטה מראה איך האפליקציה עשויה להדפיס רשימה של מכשירים, דף אחרי דף:

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

השלבים הבאים

עכשיו כשאתם יודעים איך ה-API פועל, נסו את הדוגמאות בעזרת מדריך למתחילים ב-Java, NET. או Python.