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

API khách hàng cho phép kiểm soát có lập trình các thiết bị và cấu hình để thiết lập tự động cho Android. Tài liệu này giới thiệu API cho nhà cung cấp giải pháp quản lý di động dành cho doanh nghiệp (EMM) và nhà phát triển CNTT cho doanh nghiệp. Sau khi đọc tài liệu này, bạn nên hiểu rõ các tài nguyên cốt lõi được dùng trong API và cách các tài nguyên này tương tác. Nếu bạn mới sử dụng phương thức đăng ký tự động đăng ký, hãy đọc phần giới thiệu ngắn về android.com.

Tổng quan

API khách hàng giúp các tổ chức mua thiết bị thiết lập tự động của Android. Ứng dụng hoặc công cụ của bạn có thể giúp quản trị viên CNTT làm những việc sau:

  • Tạo, chỉnh sửa và xoá cấu hình cấp phép.
  • Áp dụng hoặc xoá cấu hình cho một thiết bị.
  • Chọn cấu hình mặc định cho mọi thiết bị được thêm vào quy trình thiết lập tự động từ nay về sau.

Thông qua API này, quản trị viên CNTT cũng có thể huỷ đăng ký cho các thiết bị khỏi quy trình đăng ký tự động. Để quản lý người dùng trong tổ chức hoặc chấp nhận Điều khoản dịch vụ, quản trị viên CNTT sẽ sử dụng cổng thiết lập tự động.

Người dùng thông thường của API này có thể là:

  • Nhà cung cấp dịch vụ EMM (quản lý thiết bị di động doanh nghiệp) thêm tính năng hỗ trợ thiết lập tự động cho bảng điều khiển của họ.
  • Các nhà phát triển CNTT dành cho doanh nghiệp tạo ra các công cụ giúp tự động hoá các tác vụ thiết lập tự động.

Tài nguyên cốt lõi

Cấu hình và thiết bị là tài nguyên cốt lõi mà bạn sử dụng trong API. Tổ chức cũng có thể tạo các cấu hình và thiết bị bằng cổng đăng ký tự động đăng ký.

Mối quan hệ giữa thiết bị và tài nguyên của khách hàng

Cấu hình
Quản trị viên CNTT thiết lập các tuỳ chọn cấp phép cho các thiết bị bằng cách sử dụng một cấu hình. Cấu hình bao gồm các chính sách của EMM dành cho thiết bị di động và thông tin liên hệ sẽ hiển thị để giúp người dùng. Cấu hình là trọng tâm của API, vì vậy bạn sẽ sử dụng các cấu hình đó trong nhiều phương thức. Để tìm hiểu thêm, hãy xem phần Cấu hình ở bên dưới.
Thiết bị
Một thiết bị Android có khả năng thiết lập tự động mà tổ chức mua qua đại lý của họ. Áp dụng một cấu hình để đưa thiết bị vào chương trình đăng ký tự động đăng ký. Thiết bị có mã phần cứng và siêu dữ liệu đính kèm. Để tìm hiểu thêm, hãy xem phần Thiết bị bên dưới.
DPC (Trình quản lý thiết bị di động)
Mã tham chiếu chỉ có thể đọc đến DPC của EMM (trình kiểm soát chính sách thiết bị). Thêm DPC vào cấu hình để chọn giải pháp EMM cho thiết bị. Tất cả DPC mà API liệt kê đều hỗ trợ thiết lập tự động và có sẵn trong Google Play. Để tìm hiểu thêm, hãy xem Dpc.

Để 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.

Cấu hình

Tài nguyên API Configuration kết hợp những nội dung sau:

  • Đã cài đặt DPC của EMM trên các thiết bị.
  • Các chính sách EMM được thực thi trên các thiết bị.
  • Thông tin liên hệ hiển thị trên thiết bị để trợ giúp người dùng trong quá trình thiết lập.

Khi sử dụng API này, ứng dụng của bạn có thể quản lý cấu hình cho quản trị viên CNTT. Gọi API này để tìm nạp, tạo, cập nhật và xoá cấu hình. Ví dụ bên dưới cho biết cách tạo một cấu hình mới:

Java

// Add metadata to help the device user during provisioning.
Configuration configuration = new Configuration();
configuration.setConfigurationName("Sales team");
configuration.setCompanyName("XYZ Corp.");
configuration.setContactEmail("it-support@example.com");
configuration.setContactPhone("+1 (800) 555-0112");
configuration.setCustomMessage("We're setting up your phone. Call or email for help.");

// Set the DPC that zero-touch enrollment downloads and installs from Google Play.
configuration.setDpcResourcePath(dpc.getName());

// Set the JSON-formatted EMM provisioning extras that are passed to the DPC.
configuration.setDpcExtras("{"
      + "\"android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED\":true,"
      + "\"android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE\":{"
      + "\"default_min_password_length\":6,"
      + "\"company_name\":\"XYZ Corp\","
      + "\"management_server\":\"emm.example.com\","
      + "\"terms_url\":\"https://www.example.com/policies/terms/\","
      + "\"allowed_user_domains\":\"[\\\"example.com\\\", \\\"example.org\\\"]\""
      + "}"
      + "}");

// Create the new configuration on the server.
AndroidProvisioningPartner.Customers.Configurations.Create request =
      service.customers().configurations().create(customerAccount, configuration);
Configuration response = request.execute();

.NET

// Add metadata to help the device user during provisioning.
Configuration configuration = new Configuration
{
    ConfigurationName = "Sales team",
    CompanyName = "XYZ Corp.",
    ContactEmail = "it-support@example.com",
    ContactPhone = "+1 (800) 555-0112",
    CustomMessage = "We're setting up your phone. Call or email for help."
};

// Set the DPC that zero-touch enrollment downloads and installs from Google Play.
configuration.DpcResourcePath = dpc.Name;

// Set the JSON-formatted EMM provisioning extras that are passed to the DPC.
configuration.DpcExtras = @"{
    ""android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED"":true,
    ""android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE"":{
    ""default_min_password_length"":6,
    ""company_name"":""XYZ Corp"",
    ""management_server"":""emm.example.com"",
    ""terms_url"":""https://www.example.com/policies/terms/"",
    ""allowed_user_domains"":""[\""example.com\"", \""example.org\""]""
  }
}";

// Create the new configuration on the server.
var request = service.Customers.Configurations.Create(configuration, customerAccount);
var response = request.Execute();

Python

# Add metadata to help the device user during provisioning.
configuration = {
    'configurationName': 'Sales team',
    'companyName': 'XYZ Corp.',
    'contactEmail': 'it-support@example.com',
    'contactPhone': '+1 (800) 555-0112',
    'customMessage': 'We\'re setting up your phone. Call or email for help.'}

# Set the DPC that zero-touch enrollment installs from Google Play.
configuration['dpcResourcePath'] = dpc['name']

# Set the JSON-formatted EMM provisioning extras that are passed to the DPC.
configuration['dpcExtras'] = '''{
    "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED":true,
    "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE":{
      "default_min_password_length":6,
      "company_name":"XYZ Corp",
      "management_server":"emm.example.com",
      "terms_url":"https://www.example.com/policies/terms/",
      "allowed_user_domains":"[\\"example.com\\", \\"example.org\\"]"}
}'''

# Create the new configuration on the server.
response = service.customers().configurations().create(
    parent=customer_account, body=configuration).execute()

Khi bạn cập nhật cấu hình bằng bản vá API, hãy nhớ thêm mặt nạ trường (field mask) hoặc một giá trị cho mọi trường mà bạn không muốn là null. Xem phần Cấu hình mặc định (bên dưới) để biết ví dụ về cách cập nhật cấu hình hiệu quả.

Xoá cấu hình

Bạn không thể xoá một cấu hình nếu cấu hình đó vẫn được áp dụng cho các thiết bị. Nếu bạn cố gắng xoá một cấu hình đang sử dụng, phương thức API sẽ trả về một mã trạng thái HTTP 400 Bad Request và một thông báo giải thích số lượng thiết bị sử dụng cấu hình đó. Hãy gọi customers.devices.removeConfiguration để xoá cấu hình khỏi các thiết bị trước khi thử lại.

Cấu hình mặc định

Thiết lập tự động hoạt động hiệu quả nhất khi tổ chức đặt một cấu hình mặc định để áp dụng cho mọi thiết bị mới mà tổ chức mua. Bạn có thể cân nhắc việc nhắc quản trị viên CNTT đặt cấu hình mặc định nếu chưa đặt cấu hình này. Ví dụ bên dưới cho thấy cách đặt một cấu hình hiện có làm mặc định bằng cách đặt isDefault thành true:

Java

// Send minimal data with the request. Just the 2 required fields.
// targetConfiguration is an existing configuration that we want to make the default.
Configuration configuration = new Configuration();
configuration.setIsDefault(true);
configuration.setConfigurationId(targetConfiguration.getConfigurationId());

// Call the API, including the FieldMask to avoid setting other fields to null.
AndroidProvisioningPartner.Customers.Configurations.Patch request = service
      .customers()
      .configurations()
      .patch(targetConfiguration.getName(), configuration);
request.setUpdateMask("isDefault");
Configuration results = request.execute();

.NET

// Send minimal data with the request. Just the 2 required fields.
// targetConfiguration is an existing configuration that we want to make the default.
Configuration configuration = new Configuration
{
    IsDefault = true,
    ConfigurationId = targetConfiguration.ConfigurationId,
};

// Call the API, including the FieldMask to avoid setting other fields to null.
var request = service.Customers.Configurations.Patch(configuration,
                                                     targetConfiguration.Name);
request.UpdateMask = "IsDefault";
Configuration results = request.Execute();

Python

# Send minimal data with the request. Just the 2 required fields.
# target_configuration is an existing configuration we'll make the default.
configuration = {
    'isDefault': True,
    'configurationId': target_configuration['configurationId']}

# Call the API, including the FieldMask to avoid setting other fields to null.
response = service.customers().configurations().patch(
    name=target_configuration['name'],
    body=configuration, updateMask='isDefault').execute()

Chỉ có thể có một cấu hình mặc định. Tạo cấu hình mặc định mới, đặt trường isDefault của cấu hình trước thành false. Bạn có thể cần phải làm mới mọi thực thể Configuration đã lưu vào bộ nhớ đệm để xem các giá trị chính xác trong các trường isDefault.

Hướng dẫn người dùng thiết bị

Cấu hình thiết lập tự động hiển thị hướng dẫn tuỳ chỉnh cho người dùng trong thiết lập Trình hướng dẫn thiết lập để trợ giúp người dùng. Bạn cần cung cấp số điện thoại liên hệ và địa chỉ email cùng với tên của tổ chức quản lý thiết bị trong một cấu hình. Bạn cũng nên đưa một hoặc hai câu vào trường customMessage để cung cấp thêm thông tin chi tiết về những gì đang xảy ra với thiết bị của người dùng.

Vì người dùng sẽ không thể gọi điện hoặc gửi email từ thiết bị mà họ đang thiết lập, hãy định dạng số điện thoại và địa chỉ email để giúp họ xem nhanh thông tin dễ dàng hơn.

Thiết bị

Đại lý tạo thiết bị khi khách hàng mua các thiết bị đó để đăng ký tự động – quản trị viên CNTT không thể tạo thiết bị. Để làm việc với các thiết bị, hãy gọi các phương thức trên tài nguyên API Device. Nếu bạn cần tìm kiếm thiết bị, hãy liệt kê tất cả các thiết bị và lọc cục bộ từng lô trong ứng dụng của mình. Để xem ví dụ, hãy xem phần Kết quả được phân trang dưới đây.

Định cấu hình thiết bị

Việc áp dụng cấu hình cho một thiết bị sẽ đăng ký thiết bị đó để đăng ký tự động. Để áp dụng cấu hình, hãy gọi customers.devices.applyConfiguration. Sau khi áp dụng cấu hình, thiết bị sẽ tự động quy định trong lần khởi động đầu tiên hoặc lần đặt lại về trạng thái ban đầu tiếp theo. Ví dụ bên dưới cho thấy cách bạn có thể áp dụng cấu hình cho một tập hợp thiết bị:

Java

List<Device> devices = getDevicesToConfigure(service);
Configuration configurationToApply = getConfigurationToApply(service);

// Loop through the collection and apply the configuration to each device. This might
// take some time if the collection contains many devices.
for (Device device : devices) {
    System.out.println(device.getDeviceIdentifier().getImei());

    // Wrap the device ID in a DeviceReference.
    DeviceReference deviceRef = new DeviceReference();
    deviceRef.setDeviceId(device.getDeviceId());

    // Build and send the request to the API.
    CustomerApplyConfigurationRequest body = new CustomerApplyConfigurationRequest();
    body.setConfiguration(configurationToApply.getName());
    body.setDevice(deviceRef);

    AndroidProvisioningPartner.Customers.Devices.ApplyConfiguration request = service
          .customers()
          .devices()
          .applyConfiguration(customerAccount, body);
    request.execute();
}

.NET

IList<Device> devices = GetDevicesToConfigure(service);
Configuration configurationToApply = GetConfigurationToApply(service);

// Loop through the collection and apply the configuration to each device. This might
// take some time if the collection contains many devices.
foreach (Device device in devices)
{
    Console.WriteLine(device.DeviceIdentifier.Imei);

    // Wrap the device ID in a DeviceReference.
    var deviceRef = new DeviceReference
    {
        DeviceId = device.DeviceId
    };

    // Build and send the request to the API.
    CustomerApplyConfigurationRequest body = new CustomerApplyConfigurationRequest
    {
        Configuration = configurationToApply.Name,
        Device = deviceRef
    };
    var request = service.Customers.Devices.ApplyConfiguration(body,
                                                               customerAccount);
    request.Execute();
}

Python

devices = get_devices_to_configure(service)
configuration = get_configuration_to_apply(service)

# Loop through the collection and apply the configuration to each device.
# This might take some time if the collection contains many devices.
for device in devices:
  print(device['deviceIdentifier']['imei'])

  # Wrap the device ID in a DeviceReference.
  device_ref = {'deviceId': device['deviceId']}

  # Build and send the request to the API.
  body = {'configuration': configuration['name'], 'device': device_ref}
  service.customers().devices().applyConfiguration(
      parent=customer_account, body=body).execute()

Để xoá cấu hình khỏi một thiết bị, hãy gọi customers.devices.removeConfiguration. Thay đổi này sẽ có hiệu lực sau khi đặt lại thiết bị về trạng thái ban đầu.

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

Quản trị viên CNTT có thể huỷ xác nhận quyền sở hữu một thiết bị để xoá thiết bị đó khỏi quy trình thiết lập tự động. Quản trị viên CNTT có thể huỷ xác nhận quyền sở hữu một thiết bị mà họ muốn di chuyển sang tài khoản khác, bán hoặc trả lại đại lý. Gọi phương thức customers.devices.unclaim để huỷ xác nhận quyền sở hữu một thiết bị của một tổ chức.

Ví dụ dưới đây cho biết cách huỷ xác nhận quyền sở hữu một thiết bị bằng số IMEI và tên nhà sản xuất:

Java

// Wrap the hardware ID and manufacturer values in a DeviceIdentifier.
// Then wrap the DeviceIdentifier in a DeviceReference.
DeviceIdentifier identifier = new DeviceIdentifier();
identifier.setImei("123456789012347");
identifier.setManufacturer("Google");
DeviceReference reference = new DeviceReference();
reference.setDeviceIdentifier(identifier);

// Create the body of the request.
CustomerUnclaimDeviceRequest body = new CustomerUnclaimDeviceRequest();
body.setDevice(reference);

// Call the API method to unclaim the device from the organization.
service.customers().devices().unclaim(customerAccount, body).execute();

.NET

// Wrap the hardware ID and manufacturer values in a DeviceIdentifier.
// Then wrap the DeviceIdentifier in a DeviceReference.
DeviceIdentifier identifier = new DeviceIdentifier
{
    Imei = "123456789012347",
    Manufacturer = "Google"
};
DeviceReference reference = new DeviceReference();
reference.DeviceIdentifier = identifier;

// Create the body of the request.
CustomerUnclaimDeviceRequest body = new CustomerUnclaimDeviceRequest();
body.Device = reference;

// Call the API method to unclaim the device from the organization.
service.Customers.Devices.Unclaim(body, customerAccount).Execute();

Python

# Wrap the hardware ID and manufacturer values in a DeviceIdentifier.
# Then wrap the DeviceIdentifier in a DeviceReference.
identifier = {'imei': '123456789012347', 'manufacturer': 'Google'}
reference = {'deviceIdentifier': identifier}

# Create the body of the request.
body = {'device': reference}

# Call the API method to unclaim the device from the organization.
service.customers().devices().unclaim(
    parent=customer_account, body=body).execute()

Siêu dữ liệu thiết bị

Quản trị viên CNTT có thể xem siêu dữ liệu mà đại lý đính kèm vào thiết bị. Hiển thị siêu dữ liệu thiết bị này trong ứng dụng của bạn để giúp quản trị viên CNTT nhận ra thiết bị.

Để tìm hiểu thêm về siêu dữ liệu mà bạn có thể thấy, hãy đọc hướng dẫn về Siêu dữ liệu thiết bị dành cho đại lý.

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

Phương thức API customers.devices.list 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ư customers.list) sẽ 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ý danh sách lớ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 hay không. Nếu nextPageToken không phải là null, ứng dụng của bạn có thể sử dụng công cụ này để tìm nạp một trang thiết bị khác bằng cách gọi lại phương thức này. Bạn cần đặt giới hạn trên cho số lượng thiết bị trong tham số pageSize. Nếu nextPageTokennull, tức là ứng dụng của bạn đã yêu cầu trang cuối cùng.

Phương thức ví dụ bên dưới cho biết cách ứng dụng của bạn có thể in danh sách thiết bị, từng trang một:

Java

private void printDevices(AndroidProvisioningPartner service, String customerAccount,
      String pageToken) throws IOException {

    // Call the API to get a page of Devices. Send a page token from the method argument.
    // If the page token is null, the API returns the first page.
    AndroidProvisioningPartner.Customers.Devices.List request =
          service.customers().devices().list(customerAccount);
    request.setPageSize(50L);
    request.setPageToken(pageToken);
    CustomerListDevicesResponse response = request.execute();

    // 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 & print the devices.
    if (response.getNextPageToken() != null) {
        this.printDevices(service, customerAccount, response.getNextPageToken());
    }
}

.NET

private void PrintDevices(AndroidProvisioningPartnerService service, String customerAccount,
                          String pageToken)
{
    // Call the API to get a page of Devices. Send a page token from the method argument.
    // If the page token is null, the API returns the first page.
    var request = service.Customers.Devices.List(customerAccount);
    request.PageSize = 50;
    request.PageToken = pageToken;
    var response = request.Execute();

    // 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(service, customerAccount, response.NextPageToken);
    }
}

Python

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

  # Call the API to get a page of Devices. Send a page token from the method
  # argument. If the page token is None, the API returns the first page.
  response = service.customers().devices().list(
      parent=customer_account, pageSize=50, pageToken=page_token).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(service, customer_account, response['nextPageToken'])

Bắt đầu

Tiếp theo, hãy đọc cách uỷ quyền các lệnh gọi API trong bài viết Uỷ quyền. Nếu bạn muốn khám phá các API, hãy xem hướng dẫn bắt đầu nhanh dành cho Java, .NETPython. Bạn có thể dùng colab để xem ví dụ về lệnh gọi API và thử nghiệm việc tự gọi API.