網路與電話

本指南的功能說明網路和電話管理 可在裝置政策中執行 控制器 (DPC) 應用程式。這份文件內含程式碼 使用範例,您也可以使用 Test DPC 應用程式 Android 企業功能的程式碼範例來源。

DPC 應用程式可在個人裝置或裝置擁有者的設定檔擁有者模式下執行 模式。下表會指出哪些功能 DPC 以設定檔擁有者模式或裝置擁有者模式執行時才能使用 模式

功能 設定檔擁有者 裝置擁有者
存取工作聯絡人 跨資料夾
確認 確保工作流量的安全網路連線
設定 單一無線網路 ID (多個區域)
指定 適用於工作資料夾的不同撥號程式

存取個人資料夾中的工作聯絡人

EMM 可讓使用者的個人資料夾存取工作聯絡人, 使用者可以透過區域搜尋功能存取使用者的個人和工作聯絡人 取得遠端目錄查詢。個人裝置上的個人裝置只能有一個撥號程式 設定檔可以撥打和接聽個人通話,以及撥打工作電話。此外, 工作聯絡人已妥善整合至系統 UI。如果工作資料夾是 加密後,個人資料夾也無法取得其資料。

與系統 UI 整合

系統 UI 會透過公事包圖示顯示工作來電。 callLog 也會顯示 圖示,藉此指派工作來電和撥出電話。個人撥號程式 聯絡人應用程式可以使用遙控器顯示工作聯絡人的來電顯示資訊 目錄查詢,因此聯絡人不需要已與 本機裝置。訊息應用程式可以執行當地的來電顯示與搜尋功能。

Android 相容性定義 文件 (CDD) 包含需求條件 顯示在預設撥號程式中的工作聯絡人,以及需要 聯絡人和訊息應用程式會獲得標記,代表他們是工作人員

使用者可以存取及搜尋工作聯絡人

使用者可以透過自己的個人資料夾存取及撥打電話給工作聯絡人, 顯示在撥號應用程式的搜尋畫面中。使用者可搜尋公司 透過自動完成功能同步處理到裝置本機的聯絡人 執行遠端目錄查詢

控管主要設定檔中的工作聯絡人

DPC 控管了搜尋公司聯絡人的權限。在設定檔擁有者中執行 模式,DPC 會管理個人資料夾中工作聯絡人的瀏覽權限。 詳情請參閱「建立裝置政策」一文 控制器

根據預設,系統會啟用透過個人資料夾搜尋工作聯絡人的功能。

確保針對工作流量使用安全的網路連線

在裝置擁有者模式或設定檔擁有者模式 (裝置政策) 中運作 控制器可以使用永久連線的虛擬私人網路 (VPN) 連線至 強制應用程式透過指定的 VPN 應用程式傳遞流量,但應用程式無法 被繞過DPC 可使用永久連線 VPN 連線 來自工作資料夾或受管理裝置的流量會經由 VPN 服務傳遞。 不需要使用者介入這項程序會為 工作資料夾中的持續流量。

關於永久連線 VPN 連線

做為系統架構的一環,VPN 轉送會自動管理 且無法略過 VPN 服務啟動時間內,如果 VPN 服務連線中斷 鎖定模式,流量無法洩漏到開放的網際網路。應用程式 實作 VpnService, 永久連線 VPN 提供一種架構,能讓你透過 並持續運作VPN 服務會自動重新啟動 連線的應用程式更新,無論是使用 Wi-Fi 還是 。如果裝置重新啟動,架構就會重新啟動 VPN 連線。

VPN 服務的連線對使用者公開。換 公司擁有的裝置時,使用者不需要確認 設為永久連線模式 VPN。使用者的 VPN 網路設定允許 手動開啟「永久連線」。

如果DISALLOW_CONFIG_VPNtrue,系統會禁止使用者設定 VPN。啟用 DISALLOW_DEBUGGING_FEATURES ,防止使用者使用 ADB 偵錯指令覆寫永久連線的 VPN。 如要禁止使用者解除安裝 VPN,請呼叫 DevicePolicyManager.setUninstallBlocked

設定 VPN 服務

使用您的 Android 企業解決方案的機構已設定 VPN。

  1. 安裝 VpnService。 您可以使用符合以下項目的意圖篩選器,尋找有效的 VPN 服務: 動作 VpnService.SERVICE_INTERFACE
  2. 宣告 VpnService 在受權限保護的應用程式資訊清單中 BIND_VPN_SERVICE
  3. 設定 VpnService 由系統啟動請避免將 VPN 應用程式設為自行啟動 ,並控製本身的生命週期。
  4. [受管理] 屬性設為 設定 VPN 應用程式 (請參閱下方範例)。

啟用永久連線 VPN 連線

DPC 可透過以下方式,設定永久連線的 VPN 連線: 撥號中 DevicePolicyManager.setAlwaysOnVpnPackage()

系統會自動授予這個連線,並在重新啟動後繼續。如果 lockdownEnabled 為 false,從啟動時間開始,網路流量可能不會受到保護 手機重新啟動後,VPN 連線若您不想停止 網路連線時,或是 VPN 非必要的 VPN 連線。

確認永久連線 VPN 連線

DPC 可以讀取管理永久連線 VPN 的套件名稱 與目前使用者的連線 DevicePolicyManager.getAlwaysOnVpnPackage().

如果沒有這類套件,或是在系統設定中建立了 VPN 應用程式,會傳回 null

範例

TestDPC 應用程式中,AlwaysOnVpnFragment.java 會使用這些 API 啟用永久連線 VPN 連線的設定。

在下列範例中:

  • 代管 叢集設定 VPN 服務會 DevicePolicyManager 使用 setApplicationRestrictions() 方法。
  • 受管理的設定會使用任意鍵/值組合,而且這個範例應用程式 會在其他地方使用,做為 VPN 的網路設定 (請參閱 檢查受管理的設定)。
  • 這個範例會將 Android 套件安裝程式加入拒絕清單, 透過 VPN 更新系統套件所有使用者的網路流量 工作資料夾或裝置會透過這個 VPN 應用程式傳送 (套件除外) 安裝程式;更新會使用開放網際網路。
  • 接著,DevicePolicyManager 會為以下項目啟用永久連線 VPN 連線: 使用 Cloud VPN 套件 setAlwaysOnVpnPackage(), 並啟用鎖定模式

Kotlin

// Set VPN's managed configurations
val config = Bundle().apply {
  putString(Extras.VpnApp.ADDRESS, "192.0.2.0")
  putString(Extras.VpnApp.IDENTITY, "vpn.account1")
  putString(Extras.VpnApp.CERTIFICATE, "keystore://auth_certificate")
  putStringArray(Extras.VpnApp.DENYLIST,
        arrayOf("com.android.packageinstaller"))
}

val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager

val admin = myDeviceAdminReceiver.getComponentName(this)

// Name of package to update managed configurations
val vpnPackageName = "com.example.vpnservice"

// Associate managed configurations with DeviceAdminReceiver
dpm.setApplicationRestrictions(admin, vpnPackageName, config)

// Enable always-on VPN connection through VPN package
try {
  val lockdownEnabled = true
  dpm.setAlwaysOnVpnPackage(admin, vpnPackageName, lockdownEnabled)
} catch (ex: Exception) {
  throw PolicyException()
}

Java

// Set VPN's managed configurations
final Bundle config = new Bundle();
config.putString(Extras.VpnApp.ADDRESS, "192.0.2.0");
config.putString(Extras.VpnApp.IDENTITY, "vpn.account1");
config.putString(Extras.VpnApp.CERTIFICATE, "keystore://auth_certificate");
config.putStringArray(Extras.VpnApp.DENYLIST,
                      new String[]{"com.android.packageinstaller"});

DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);

ComponentName admin = myDeviceAdminReceiver.getComponentName(this);

// Name of package to update managed configurations
final String vpnPackageName = "com.example.vpnservice";

// Associate managed configurations with DeviceAdminReceiver
dpm.setApplicationRestrictions(admin, vpnPackageName, config);

// Enable always-on VPN connection through VPN package
try {
  boolean lockdownEnabled = true;
  dpm.setAlwaysOnVpnPackage(admin, vpnPackageName, lockdownEnabled));
} catch (Exception ex) {
  throw new PolicyException(...);
}

跨區域設定單一無線網路 ID

在裝置擁有者模式或設定檔擁有者模式 (裝置政策) 中運作 控制器 (DPC) 可以連結多個憑證授權單位 (CA) 憑證 且具備單一無線網路設定完成這項設定後 能夠連線到網路名稱相同的無線存取點,或 服務集 ID (SSID),但採用不同的 CA 設定 憑證如果機構的無線網路位於 且每個區域都必須 憑證授權單位。例如,法律簽名可能會要求提供當地 需要建立區域性 CA 的憑證授權單位

注意:Android 支援 setCaCertificate 自 API 18 (Jelly Bean) 以來,IT 管理員都必須佈建網路 分別使用不同的憑證授權單位,確保裝置在每個端點上都能順暢進行驗證 存取同一區域,無論所在區域為何

指定用於識別伺服器的 CA 憑證

如果要指定使用 X.509 憑證清單來識別伺服器 SSID,使用 WifiEnterpriseConfig.setCaCertificates() 在無線設定中加入所有相關 CA。

如果伺服器的 CA 與其中一個指定憑證相符,則伺服器憑證即有效。 系統會自動將預設名稱指派給憑證,並用於 此外還會從 0 自動調整資源配置 您完全不必調整資源調度設定 WifiManager 並在安裝憑證後自動儲存設定 網路已啟用,在設定時移除憑證 已刪除。

如要取得與無線設定相關聯的所有 CA 憑證,請使用 WifiEnterpriseConfig.getCaCertificates():傳回 X509Certificate 物件。

使用多個 CA 憑證新增無線設定

  1. 驗證伺服器身分:
    1. 載入 X.509 CA 憑證。
    2. 載入用戶端的私密金鑰和憑證。如需讀取憑證檔案的說明範例,請參閱「使用 HTTPS 和 SSL 確保安全性」。
  2. 建立新的 WifiConfiguration 並設定 SSID 和金鑰管理功能。
  3. 設定 WifiEnterpriseConfig 執行個體。WifiConfiguration
    1. 找出含有 X509Certificate 使用 Kubernetes Engine setCaCertificates()
    2. 設定用戶端憑證、身分和密碼。
    3. 將加強式驗證通訊協定 (EAP) 和第 2 階段方法設為 建立連線的一部分
  4. 新增網路 WifiManager
  5. 啟用網路。WifiManager 會在以下期間自動儲存設定: 設定。

以下範例將步驟結合在一起:

Kotlin

// Verify the server's identity
val caCert0 = getCaCert("cert0.crt")
val caCert1 = getCaCert("cert1.crt")
val clientKey = getClientKey()
val clientCert = getClientCert()

// Create Wi-Fi configuration
val wifiConfig = WifiConfiguration().apply {
  SSID = "mynetwork"
  allowedKeyManagement.set(KeyMgmt.WPA_EAP)
  allowedKeyManagement.set(KeyMgmt.IEEE8021X)

  // Set up Wi-Fi enterprise configuration
  enterpriseConfig.setCaCertificates(arrayOf<X509Certificate>(caCert0, caCert1))
  enterpriseConfig.setClientKeyEntry(clientKey, clientCert)
  enterpriseConfig.setIdentity("myusername")
  enterpriseConfig.setEapMethod(Eap.TLS)
  enterpriseConfig.setPhase2Method(Phase2.NONE)
}


// Add network
val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
val netId = wifiManager.addNetwork(wifiConfig)

// Enable network
if (netId < 0) {
  // Error creating new network
} else {
  wifiManager.enableNetwork(netId, true)
}

Java

// Verify the server's identity
X509Certificate caCert0 = getCaCert("cert0.crt");
X509Certificate caCert1 = getCaCert("cert1.crt");
PrivateKey clientKey = getClientKey();
X509Certificate clientCert = getClientCert();

// Create Wi-Fi configuration
WifiConfiguration wifiConfig = new WifiConfiguration();
wifiConfig.SSID = "mynetwork";
wifiConfig.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
wifiConfig.allowedKeyManagement.set(KeyMgmt.IEEE8021X);

// Set up Wi-Fi enterprise configuration
wifiConfig.enterpriseConfig.setCaCertificates(new X509Certificate[] {caCert0, caCert1});
wifiConfig.enterpriseConfig.setClientKeyEntry(clientKey, clientCert);
wifiConfig.enterpriseConfig.setIdentity("myusername");
wifiConfig.enterpriseConfig.setEapMethod(Eap.TLS);
wifiConfig.enterpriseConfig.setPhase2Method(Phase2.NONE);

// Add network
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
int netId = wifiManager.addNetwork(wifiConfig);

// Enable network
if (netId < 0) {
  // Error creating new network
} else {
  wifiManager.enableNetwork(netId, true);
}

為工作資料夾指定個別的撥號程式

您可以將要在工作資料夾中使用的個別撥號應用程式加入許可清單, 可以是撥號程式本身或採用 IP 位址的 Voice (VoIP) 應用程式 ConnectionService 用於呼叫後端的 API。這能提供相同的整合式系統 UI 撥號 存取工作資料夾中的 IP 網路語音傳遞應用程式,進而有效完成工作 撥號程式是核心功能公司通話帳戶的來電 區分與個人通話帳戶的來電。

使用者可以選擇透過許可清單中的工作撥號程式撥打及接聽電話 使用手機帳戶。使用該撥號程式撥打或接聽工作電話的所有電話 電話帳戶都會記錄在工作資料夾的 CallLog 。工作撥號程式會維護工作專用的通話記錄,但僅限存取 工作聯絡人。線路切換通話是由主要撥號程式處理 並儲存在個人通話記錄中如果工作資料夾遭到刪除,系統會提供通話記錄 所有與該工作資料夾相關聯的資料夾也會一併刪除 資料。

第三方應用程式必須導入 ConnectionService

需要撥打電話及設定通話的第三方 IP 網路語音傳遞應用程式 整合至手機內建的應用程式,即可實作 ConnectionService 也能使用 Google Cloud CLI 或 Compute Engine API如要使用任何 VoIP 服務來處理工作通話,都必須符合這項條件。這些應用程式 可能在將來電視為傳統行動網路通話 例如,它們會顯示在內建系統撥號程式和通話記錄中。如果 應用程式實作 ConnectionService 安裝於工作資料夾,則只能透過撥號程式存取 安裝在該工作資料夾中。

開發人員導入 ConnectionService, 他們應將該檔案加入應用程式的資訊清單檔案,並註冊 PhoneAccount 使用 TelecomManager。 電話帳戶代表撥打或接聽電話的獨特方法。 且每個 ID 都可以有多個 PhoneAccounts ConnectionService。手機帳戶註冊完成後,使用者 可以透過撥號程式設定啟用

系統 UI 整合與通知

系統 UI 為使用者提供一致且整合的撥號體驗 如果第三方應用程式採用 ConnectionService 做為發出呼叫的後端在工作資料夾中使用應用程式時,系統會建立公事包 圖示會顯示外來通話和狀態列。 工作資料夾中安裝的 ConnectionService 可以使用 系統撥號程式 或是另外建立一個工作用的撥號程式可以是單一應用程式 不同的應用程式

撥號應用程式會透過以下方式判斷自己是否正在撥打或接聽公司電話: 正在檢查標記 android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL。 如果通話是公司通話,撥號程式會在應用程式中加入 工作徽章 (公事包圖示):

Kotlin

// Call placed through a work phone account. getCurrentCall() is defined by the
// dialer.
val call = getCurrentCall()
if (call.hasProperty(android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL)) {
  // Set briefcase icon
}

Java

// Call placed through a work phone account. getCurrentCall() is defined by the
// dialer.
Call call = getCurrentCall();
if (call.hasProperty(android.telecom.Call.Details.PROPERTY_ENTERPRISE_CALL)) {
  // Set briefcase icon
}