איך זה עובד

מבוא

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

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

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

מושגי API

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

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

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

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

יצירת לקוחות

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

אפשר לקרוא ל-method של ה-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()

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

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

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

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

כדי לטעון בעלות על מכשיר של לקוח אחר, צריך לבטל את הבעלות על המכשיר של הלקוח הקודם (מידע נוסף מופיע בהמשך). שיטות התלונה מאמתים את השדות ב-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()

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

הארגון שלך יכול לבטל את הבעלות על מכשיר של הלקוח. ביטול הבעלות על מכשיר גורם להסרת המכשיר מההרשמה דרך הארגון. מפיץ יכול לבטל את הבעלות על מכשיר שהוא רוצה להעביר לחשבון אחר, להחזיר או שהבעלות עליו הוכרזה בטעות. קוראים ל-method 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 לשנות מכשירים, צריך לבדוק שהארגון שלך תבע בעלות על המכשיר לפני קריאה ל-method של ה-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 כולל גרסאות אסינכרוניות של ה-methods של המכשיר. השיטות האלה מאפשרות עיבוד באצווה של מכשירים רבים, בעוד שהשיטות הסינכרוניות מעבדות מכשיר אחד לכל בקשת API. שמות השיטות האסינכרוניים יש סיומת אסינכרונית, לדוגמה 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)

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

תוצאות בדף

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

אחרי שמפעילים את שיטת ה-API, בודקים אם התגובה כוללת ערך בשדה nextPageToken. אם הערך של nextPageToken הוא לא null, האפליקציה יכולה להשתמש בו כדי לאחזר דף נוסף של מכשירים על ידי קריאה חוזרת ל-method. צריך להגדיר מגבלה עליונה למספר המכשירים הפרמטר 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. אפשר להשתמש ב-colab כדי להציג דוגמאות לקריאות ל-API ולנסות לקרוא ל-API בעצמכם.