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

Giới thiệu

API đăng ký không tiếp xúc giúp người bán lại thiết bị tự động hoá việc 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:

  • 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.

Tài liệu này giới thiệu API và giải thích các mẫu. Nếu bạn muốn tự khám phá API, hãy thử hướng dẫn 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ị
Thiết bị Android hoặc ChromeOS có thể đăng ký không cần chạm mà tổ chức của bạn bán cho khách hàng. Thiết bị có mã nhận dạng phần cứng, siêu dữ liệu và khiếu nại của khách hàng. 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 mã 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 đến thiết bị 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 bài viết 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ả các phương thức và tài nguyên API mà ứng dụng của bạn có thể sử 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, khách hàng sẽ quản lý quyền truy cập của nhân viên vào cổng thông tin — bạn không thể chỉnh sửa người dùng của khách hàng bằ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ò của chủ sở hữu và quản trị viên đối với nhân viên của khách hàng, hãy đọc bài viết Người dùng cổng thông tin.

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 thiết bị sẽ thêm thiết bị đó vào quy trình đăng ký không tiếp xúc và cho phép khách hàng định cấu hình chế độ cài đặt cấp phép.

Bản ghi cấp phép của thiết bị có một mục dành cho quy trình 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 phương thức partners.devices.claim hoặc partners.devices.claimAsync với đối số là khách hàng. Luôn cung cấp SECTION_TYPE_ZERO_TOUCH làm giá trị cho sectionType.

Bạn cần huỷ xác nhận quyền sở hữu (xem bên dưới) thiết bị của một 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 một 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 cho biết cách xác nhận quyền sở hữu 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ỷ xác nhận quyền sở hữu thiết bị của khách hàng. 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 đối với một thiết bị mà họ muốn di chuyển sang một tài khoản khác, trả lại hoặc 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ài khoản của các nhà cung cấp khác.
  • Bạn có thể xem khách hàng và thiết bị của nhà cung cấp, đồng thời 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 khách hàng của nhà cung cấp.

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ò của tài khoản phải là Chủ sở hữu thì bạn mới có thể tạo 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 tập hợ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 đối với thiết bị mà 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 có thể chỉnh sửa 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 quyền sở hữu 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 các 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 các phương thức đồng bộ 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ộ 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 diễn ra trong thời gian dài. Một lệnh gọi thành công đến một phương thức không đồng bộ sẽ trả về một tệp tham chiếu đến thao tác trong phản hồ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 toán tử 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 cho biết cách bạn có thể thực hiện việc này. Trong ứng dụng của riêng mình, bạn 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 hoàn tất, API sẽ cập nhật thao tác đó bằng kết quả – ngay cả khi tất cả hoặc không có tác vụ 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 hiệu quả xem có tác vụ nào không thành công hay không và tránh lặp lại các 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 hoạt động. Thứ tự danh sách khớp với các tác vụ 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ụ có thành công hay không bằng cách sử dụ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 điển hình 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 phần 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 thông tin này để ước tính thời gian hoàn tất. 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 nội dung cập nhật trong thao tác. 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 dưới đây cho thấy cách một ứng dụng có thể sử dụng siêu dữ liệu tiến trình để đặt khoảng thời gian thăm dò ý kiến. 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ò ý kiến. 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 một phương pháp thăm dò ý kiến phù hợp với người dùng ứng dụng. 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ề danh sách thiết bị rất lớn. Để giảm kích thước phản hồi, phương thức này và các phương thức API khác (chẳng hạn như partners.devices.findByIdentifier) hỗ trợ kết quả được phân trang. 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ý các danh sách lớn theo từng trang.

Sau khi gọi phương thức API, hãy kiểm tra xem phản hồi có bao gồm giá trị cho nextPageToken hay không. Nếu nextPageToken không phải là null, ứng dụng của bạn có thể sử dụng nó để 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 trang cùng một lúc:

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. Bạn có thể sử dụng colab để xem các ví dụ về lệnh gọi API và tự thử nghiệm cách gọi API.