Cách thức hoạt động

Giới thiệu

API thiết lập tự động giúp đại lý thiết bị tự động hoá quá trình tích hợp. Các công cụ bán hàng của tổ chức bạn có thể được thiết lập tự động nhờ tính năng thiết lập tự động, giúp năng suất hơn. Sử dụng API để giúp người dùng của bạn:

  • Chỉ định thiết bị đã mua cho tài khoản thiết lập tự động của khách hàng.
  • Tạo tài khoản thiết lập tự động cho khách hàng của bạn.
  • Đính kèm siêu dữ liệu đơn đặt hàng và số điện thoại của tổ chức vào các thiết bị.
  • Tạo báo cáo về các thiết bị được chỉ định cho khách hàng của bạn.

Tài liệu này giới thiệu về API và giải thích các mẫu. Nếu bạn muốn tự khám phá API, hãy thử bắt đầu nhanh về Java, .NET hoặc Python.

Khái niệm về API

Khách hàng và thiết bị là các tài nguyên cốt lõi mà bạn sử dụng trong API. Để tạo khách hàng, hãy gọi create. Bạn có thể tạo các thiết bị bằng các phương thức API xác nhận quyền sở hữu (xem bên dưới). Tổ chức của bạn cũng có thể tạo khách hàng và thiết bị bằng cổng thiết lập tự động.

Mối quan hệ với thiết bị và tài nguyên khách hàng

Khách hàng
Các công ty mà tổ chức của bạn bán thiết bị. Khách hàng có một name và một ID. Sử dụng một khách hàng khi bạn muốn xác nhận quyền sở hữu hoặc tìm thiết bị của họ. Người nhận tìm hiểu thêm, xem Customer.
Thiết bị
Một thiết bị Android hoặc ChromeOS có thể thiết lập tự động cho tổ chức của bạn bán cho khách hàng. Thiết bị có mã phần cứng, siêu dữ liệu và khách hàng xác nhận quyền sở hữu. Thiết bị là trọng tâm của API, vì vậy, bạn sử dụng chúng trong hầu hết . Để tìm hiểu thêm, hãy xem Device.
DeviceIdentifier
Đóng gói ID phần cứng, chẳng hạn như IMEI hoặc MEID, để xác định sản phẩm thiết bị. Sử dụng DeviceIdentifier để nhắm mục tiêu thiết bị mà bạn muốn tìm, cập nhật hoặc xác nhận quyền sở hữu. Để tìm hiểu thêm, hãy đọc Giá trị nhận dạng.
DeviceMetadata
Lưu trữ các cặp khoá-giá trị của siêu dữ liệu cho thiết bị. Sử dụng DeviceMetadata để lưu trữ siêu dữ liệu của tổ chức. Người nhận tìm hiểu thêm, hãy đọc bài viết Siêu dữ liệu thiết bị.

Để liệt kê tất cả phương thức API và tài nguyên mà ứng dụng của bạn có thể dùng, hãy xem Tài liệu tham khảo API.

Tạo khách hàng

Đối với thiết bị Android, đại lý chịu trách nhiệm tạo khách hàng tài khoản thay mặt cho khách hàng của mình. Khách hàng sẽ sử dụng tài khoản này để truy cập cổng thông tin tự động để định cấu hình cài đặt cấp phép cho thiết bị. Việc này không cần thiết đối với những thiết bị ChromeOS đã có tài khoản Google Workspace mà họ sẽ sử dụng để định cấu hình chế độ cài đặt cấp phép.

Bạn có thể gọi phương thức API create để tạo các tài khoản khách hàng để thiết lập tự động. Vì khách hàng của bạn thấy tên công ty trong cổng thiết lập tự động, thì người dùng ứng dụng của bạn phải xác nhận rằng URL đó là chính xác. Bạn không thể chỉnh sửa tên của khách hàng sau khi tạo khách hàng.

Bạn cần phải bao gồm ít nhất một địa chỉ email công ty, được liên kết với Tài khoản Google, trở thành chủ sở hữu. Bạn không thể sử dụng tài khoản Gmail cá nhân có API. Nếu khách hàng cần trợ giúp liên kết tài khoản, hãy gửi hướng dẫn từ Liên kết Tài khoản Google.

Sau khi bạn tạo khách hàng bằng cách gọi API, họ sẽ quản lý các nhân viên của mình quyền truy cập cổng thông tin — bạn không thể chỉnh sửa thông tin người dùng sử dụng API. Đoạn mã bên dưới cho biết cách bạn có thể tạo một khách hàng:

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

Để tìm hiểu thêm về vai trò chủ sở hữu và quản trị viên của nhân viên trong khách hàng của bạn, đọc Người dùng cổng.

Xác nhận quyền sở hữu thiết bị cho khách hàng

Sau khi khách hàng của bạn mua thiết bị, họ sẽ muốn định cấu hình cấp phép cho các thiết bị này trong tài khoản của mình. Việc xác nhận quyền sở hữu một thiết bị sẽ thêm thiết bị đó thiết lập tự động và cho phép khách hàng thiết lập cài đặt cấp phép.

Bản ghi cấp phép của thiết bị có một phần để thiết lập tự động. Bạn gán thiết bị bằng cách xác nhận phần thiết lập tự động của bản ghi cho khách hàng. Gọi partners.devices.claim hoặc partners.devices.claimAsync có phần tử khách hàng làm đối số. Luôn cung cấp SECTION_TYPE_ZERO_TOUCH làm giá trị cho sectionType

Bạn cần phải huỷ xác nhận (xem bên dưới) thiết bị của khách hàng trước khi có thể xác nhận quyền sở hữu cùng một thiết bị cho khách hàng khác. Phương thức xác nhận quyền sở hữu xác thực các trường DeviceIdentifier, bao gồm IMEI hoặc MEID hoặc số sê-ri, tên nhà sản xuất, kiểu máy và mã thiết bị được chứng thực đối với thiết bị ChromeOS khi tạo một thiết bị mới.

Đoạn mã dưới đây trình bày cách xác nhận quyền sở hữu một thiết bị:

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

Đang huỷ xác nhận quyền sở hữu thiết bị

Tổ chức của bạn có thể huỷ yêu cầu của khách hàng về một thiết bị. Huỷ xác nhận quyền sở hữu thiết bị sẽ xoá thiết bị khỏi quy trình thiết lập tự động. Đại lý có thể huỷ xác nhận quyền sở hữu thiết bị họ muốn di chuyển sang một tài khoản khác, bị trả lại hoặc nội dung bị xác nhận quyền sở hữu do nhầm lẫn. Gọi phương thức partners.devices.unclaim hoặc partners.devices.unclaimAsync để huỷ xác nhận quyền sở hữu thiết bị của khách hàng.

Nhà cung cấp

Bạn có thể sử dụng nhà cung cấp để đại diện cho đối tác đại lý trong mạng lưới đại lý của mình, tại địa phương các nhà cung cấp dịch vụ trong mạng lưới đại lý toàn cầu hoặc bất kỳ tổ chức nào bán các thiết bị khác. Nhà cung cấp giúp bạn phân tách người dùng, khách hàng và thiết bị:

  • Các nhà cung cấp mà bạn tạo không thể xem tài khoản thiết lập tự động của bạn hoặc từng nhà cung cấp tài khoản của người khác.
  • Bạn có thể xem khách hàng và thiết bị của nhà cung cấp và có thể huỷ đăng ký thiết bị của nhà cung cấp. Tuy nhiên, bạn không thể chỉ định thiết bị cho nhà cung cấp của mình khách hàng.

Sử dụng cổng thông tin để tạo nhà cung cấp cho tổ chức – bạn không thể sử dụng API. Vai trò trong tài khoản của bạn phải là Chủ sở hữu để tạo một nhà cung cấp mới. Nếu tổ chức của bạn có nhà cung cấp, bạn có thể gọi partners.vendors.list để liệt kê nhà cung cấp và partners.vendors.customers.list để có được khách hàng của nhà cung cấp. Ví dụ sau đây sử dụng cả hai phương thức này để in báo cáo cho biết trạng thái Điều khoản dịch vụ của nhà cung cấp khách hàng:

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

Nếu có một bộ sưu tập thiết bị, bạn có thể cần biết đại lý hoặc Nhà cung cấp đã xác nhận thiết bị này. Để biết mã đại lý dạng số, hãy kiểm tra giá trị của trường resellerId trong hồ sơ xác nhận quyền sở hữu của thiết bị.

Tổ chức của bạn có thể huỷ xác nhận quyền sở hữu một thiết bị do nhà cung cấp xác nhận quyền sở hữu. Đối với các lệnh gọi API khác sửa đổi thiết bị, bạn nên kiểm tra để đảm bảo rằng tổ chức của bạn đã xác nhận thiết bị đó trước khi gọi phương thức API. Ví dụ sau đây cho thấy cách thực hiện việc này:

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

Thao tác hàng loạt diễn ra trong thời gian dài

API này bao gồm các phiên bản không đồng bộ của phương thức thiết bị. Các phương thức này cho phép xử lý hàng loạt nhiều thiết bị, trong khi phương thức đồng bộ các phương thức xử lý một thiết bị cho mỗi yêu cầu API. Tên phương thức không đồng bộ có hậu tố Không đồng bộ, ví dụ: claimAsync.

Các phương thức API không đồng bộ sẽ trả về kết quả trước khi quá trình xử lý hoàn tất. Các phương thức không đồng bộ cũng giúp ứng dụng (hoặc công cụ) của bạn duy trì khả năng thích ứng cho người dùng trong khi họ chờ một hoạt động chạy trong thời gian dài hoàn tất. Ứng dụng của bạn sẽ kiểm tra trạng thái của hoạt động theo định kỳ.

Hoạt động tính toán

Bạn sẽ sử dụng Operation để theo dõi một thao tác hàng loạt chạy trong thời gian dài. Đáp lệnh gọi thành công đến một phương thức không đồng bộ sẽ trả về tham chiếu đến tác vụ trong câu trả lời. Đoạn mã JSON dưới đây cho thấy một phản hồi điển hình sau khi gọi updateMetadataAsync:

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

Mỗi thao tác chứa một danh sách các tác vụ riêng lẻ. Gọi điện operations.get để tìm hiểu thông tin về trạng thái và kết quả của các tác vụ có trong tác vụ. Đoạn mã dưới đây minh hoạ cách có thể làm việc này. Trong ứng dụng của riêng mình, bạn sẽ cần xử lý mọi lỗi.

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

Để tìm hiểu xem một thao tác đã hoàn tất hay chưa, hãy kiểm tra thao tác đó đối với trường done có giá trị true. Nếu thiếu done hoặc false thì thao tác vẫn sẽ có hiệu lực đang chạy.

Phản hồi

Sau khi một thao tác kết thúc, API sẽ cập nhật hoạt động đó cùng với kết quả – thậm chí nếu tất cả hoặc không có tác vụ riêng lẻ nào thành công. Trường response là một DevicesLongRunningOperationResponse đối tượng nêu chi tiết quá trình xử lý của từng thiết bị trong thao tác.

Kiểm tra trường successCount để tìm hiểu một cách hiệu quả xem có thao tác nào không thành công và không tránh lặp lại thông qua những danh sách kết quả lớn. Trường perDeviceStatus của DevicesLongRunningOperationResponse là danh sách OperationPerDevice thực thể nêu chi tiết từng thiết bị trong phép toán. Thứ tự danh sách khớp với các công việc trong yêu cầu ban đầu.

Mỗi việc cần làm OperationPerDevice đều chứa một trường result và một bản tóm tắt lời nhắc của yêu cầu mà máy chủ nhận được. Kiểm tra xem tác vụ thành công hay không thành công bằng trường result.

Đoạn mã JSON dưới đây cho thấy một phần của một phản hồi thông thường của một thao tác sau một lệnh gọi đến updateMetadataAsync:

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

Theo dõi tiến trình

Nếu ứng dụng của bạn cần theo dõi tiến trình, bạn nên định kỳ tìm nạp lại hoạt động. Trường metadata chứa DevicesLongRunningOperationMetadata để giúp ứng dụng kiểm tra tiến trình mới nhất của một thao tác đang chạy. Sử dụng các trường của DevicesLongRunningOperationMetadata được liệt kê trong danh sách sau để theo dõi tiến trình của hoạt động:

Trường Cách sử dụng thông thường
processingStatus Các thay đổi từ BATCH_PROCESS_PENDING thành BATCH_PROCESS_IN_PROGRESS rồi đến BATCH_PROCESS_PROCESSED khi hoạt động này diễn ra.
progress Tỷ lệ phần trăm bản cập nhật được xử lý. Ứng dụng của bạn có thể sử dụng để ước tính thời gian kết thúc. Vì progress giá trị có thể là 100 trong khi thao tác kết thúc, kiểm tra trường done của một toán tử để biết đã hoàn tất và có một kết quả.
devicesCount Cho biết số lượng bản cập nhật trong hoạt động. Chiến dịch này có thể khác với số lượt cập nhật trong yêu cầu nếu API không thể phân tích cú pháp một số nội dung cập nhật.

Ví dụ đơn giản bên dưới cho thấy cách một ứng dụng có thể sử dụng siêu dữ liệu về tiến trình để đặt khoảng thời gian thăm dò. Trong ứng dụng của mình, bạn có thể cần một thao tác tinh vi hơn trình chạy để thăm dò. Bạn cũng cần thêm tính năng xử lý lỗi.

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)

Chọn phương pháp thăm dò ý kiến phù hợp với người dùng ứng dụng của bạn. Một số người dùng ứng dụng có thể hưởng lợi từ việc cập nhật tiến trình thường xuyên nếu họ đang chờ một quy trình đã hoàn tất.

Kết quả được phân trang

Phương thức API partners.devices.findByOwner có thể trả về một danh sách rất lớn gồm nhiều thiết bị. Để giảm kích thước câu trả lời, thao tác này và các phương thức API khác (chẳng hạn như partners.devices.findByIdentifier) kết quả được phân trang hỗ trợ. Với kết quả được phân trang, ứng dụng của bạn có thể lặp lại yêu cầu và xử lý danh sách lớn trên từng trang một.

Sau khi gọi phương thức API, hãy kiểm tra xem phản hồi có chứa giá trị cho nextPageToken. Nếu nextPageToken không phải là null, ứng dụng của bạn có thể sử dụng ngôn ngữ này để tìm nạp một trang thiết bị khác bằng cách gọi phương thức đó một lần nữa. Bạn cần đặt giới hạn trên cho số lượng thiết bị trong tham số limit. Nếu nextPageTokennull, tức là ứng dụng của bạn đã yêu cầu trang cuối.

Phương thức ví dụ dưới đây cho thấy cách ứng dụng của bạn có thể in danh sách thiết bị, một mỗi lần:

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

Các bước tiếp theo

Giờ bạn đã biết cách thức hoạt động của API, hãy xem thử các ví dụ một cách bắt đầu nhanh về Java, .NET hoặc Python.