運作方式

客戶 API 可讓您透過程式,控管 Android 零接觸註冊機制的裝置和設定。本文件將向企業行動管理服務 (EMM) 供應商和企業 IT 開發人員介紹這個 API。閱讀本文件後,您應瞭解 API 中使用的核心資源,以及這些資源如何互動。如果您是第一次使用零接觸註冊機制,請參閱 android.com 簡介短片。

總覽

客戶 API 可協助購買 Android 零接觸註冊機制裝置的機構。您的應用程式或工具可以協助 IT 管理員執行以下操作:

  • 建立、編輯及刪除佈建設定。
  • 為裝置套用或移除設定。
  • 為日後新增至零接觸註冊機制的裝置選取預設設定。

透過 API,IT 管理員也可以為裝置取消註冊零接觸註冊機制。如要管理所屬機構的使用者或接受《服務條款》,IT 管理員會使用零接觸註冊機制入口網站

這個 API 的常見使用者可能會:

  • EMM 供應商在其控制台中加入零接觸註冊機制支援功能。
  • 企業 IT 開發人員建立工具來自動執行零接觸註冊機制工作。

核心資源

設定和裝置是您在 API 中使用的核心資源。機構也可以使用零接觸註冊入口網站建立設定和裝置。

裝置和客戶資源關係

設定
IT 管理員為使用設定的裝置指定佈建選項。設定包含 EMM 行動政策,以及要向使用者顯示的聯絡資訊。設定是 API 的核心,因此可在許多方法中使用。詳情請參閱下方的設定
裝置
機構向經銷商購買,且支援零接觸註冊機制的 Android 裝置。套用設定,將裝置納入零接觸註冊機制。裝置具有硬體 ID 和附加中繼資料。詳情請參閱下方的裝置一節。
裝置政策控制器 (DPC)
EMM 的 DPC (裝置政策控制器) 唯讀參考資料。在設定中加入 DPC,為裝置選取 EMM 解決方案。API 列出的所有 DPC 都支援零接觸註冊機制,並可在 Google Play 中找到。詳情請參閱 Dpc

如要列出應用程式可使用的所有 API 方法和資源,請參閱 API 參考資料

設定

Configuration API 資源結合了下列項目:

  • 在裝置上安裝 EMM 的 DPC。
  • 在裝置上強制執行的 EMM 政策。
  • 裝置上顯示的聯絡資訊,協助使用者設定裝置。

應用程式則可透過這個 API 管理 IT 管理員的設定。呼叫 API 來擷取、建立、更新及刪除設定。以下範例說明如何建立新設定:

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

使用修補程式 API 更新設定時,請記得加入欄位遮罩,或是您不想為 null 的每個欄位值。如需如何有效更新設定的範例,請參閱下文的「預設設定」一節。

刪除設定

如果設定仍未套用至裝置的設定,就無法刪除。如果您嘗試刪除使用中的設定,API 方法會傳回 HTTP 400 Bad Request 狀態碼和訊息,說明有多少裝置使用了該項設定。請呼叫 customers.devices.removeConfiguration 從裝置中移除設定,然後再試一次。

預設設定

如果機構設定了預設設定,並套用至機構購買的所有新裝置,零接觸註冊機制就能發揮最佳效用。如果尚未設定預設設定,請考慮提示 IT 管理員調整預設設定。以下範例說明如何將 isDefault 設為 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()

只能有一項預設設定。請建立新的預設設定,將先前設定的 isDefault 欄位設為 false。您可能需要重新整理任何已快取的 Configuration 例項,才能在 isDefault 欄位中查看正確的值。

引導裝置使用者

零接觸設定會在裝置的「設定精靈」中顯示自訂使用者指引,協助使用者。您必須在設定中加入聯絡電話號碼和電子郵件地址,以及管理裝置的機構名稱。我們也建議您在 customMessage 欄位中加入一或兩句話,進一步說明使用者的裝置情況。

使用者就無法從設定的裝置撥打電話或傳送電子郵件,因此請將電話號碼和電子郵件地址設為格式,方便使用者快速查看資訊。

裝置

經銷商會在客戶為了零接觸註冊機製而購買裝置時建立裝置,IT 管理員無法建立裝置。如要使用裝置,請針對 Device API 資源呼叫方法。如果您需要搜尋裝置,請列出所有裝置,然後在應用程式本機篩選每個批次。如需範例,請參閱下方的分頁結果

設定裝置

將設定套用至裝置後,系統就會為裝置註冊零接觸註冊機制。如要套用設定,請呼叫 customers.devices.applyConfiguration。套用設定後,裝置會在首次啟動或下次恢復原廠設定時自動完成佈建。以下範例說明如何將設定套用至一組裝置:

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

如要從裝置中移除設定,請呼叫 customers.devices.removeConfiguration。變更會在裝置恢復原廠設定後生效。

取消認領裝置

IT 管理員可以取消註冊裝置,藉此將裝置從零接觸註冊機制中移除。IT 管理員可能會取消認領要遷移至其他帳戶、出售或退還給經銷商的裝置。呼叫 customers.devices.unclaim 方法,從機構中取消註冊裝置。

以下範例說明如何從 IMEI 號碼和製造商名稱取消註冊裝置:

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

裝置中繼資料

IT 管理員可以查看經銷商附加至裝置的中繼資料。在應用程式中顯示這部裝置的中繼資料,以便 IT 管理員識別裝置。

如要進一步瞭解您可能會看見的中繼資料,請參閱經銷商適用的裝置中繼資料指南。

分頁結果

customers.devices.list API 方法可能會傳回非常龐大的裝置清單。如要縮減回應大小,這個方法和其他 API 方法 (例如 customers.list) 都支援分頁結果。使用分頁結果時,應用程式可以反覆要求及處理一份大型清單。

呼叫 API 方法後,請檢查回應是否包含 nextPageToken 值。如果 nextPageToken 不是 null,應用程式可再次呼叫該方法,以擷取另一頁。您必須在 pageSize 參數中設定裝置數量上限。如果 nextPageTokennull,表示應用程式要求最後一頁。

以下範例方法顯示應用程式如何輸出裝置清單,一次一個頁面:

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

立即開始

接下來,請閱讀如何在授權中授權 API 呼叫。如果您想探索 API,請參閱 Java.NETPython 的快速入門指南。您可以使用 colab 查看 API 呼叫的範例,並嘗試自行呼叫 API。