在搭載 Android 10 (API 級別 29) 以上版本的裝置中,應用程式可新增裝置的網路憑證,以便自動連線至 Wi-Fi 存取點。您可以使用 WifiNetworkSuggestion
為要連線的網路提供建議。平台最終會根據應用程式和其他來源的輸入內容,選擇接受的存取點。
在 Android 11 (API 級別 30) 以上版本中:
- 建議 API 支援佈建
PasspointConfiguration
。在 Android 11 之前,佈建PasspointConfiguration
必須使用addOrUpdatePasspointConfiguration()
API。 - 該架構會根據 TLS 為基礎的 Enterprise 建議 (EAP-TLS、EAP-TTLS 和 EAP-PEAP) 強制執行安全性要求;對這類網路的建議必須設定
Root CA certificate
和server domain name
。
- 此架構會強制執行以 EAP-SIM 為基礎的 Enterprise 建議 (EAP-SIM、EAP-AKA、EAP-AKA-PRIME) 擁有權要求;只有使用電信業者簽署的應用程式才能提供這類建議。
- 針對電信業者簽署的應用程式提供的建議,架構會自動指派與應用程式電信業者簽署相對應的電信業者 ID。如果從裝置中移除對應的 SIM 卡,這類建議就會自動停用。
Android 12 (API 級別 31) 以上版本:
您可以透過非永久的 MAC 位址啟用其他隱私保護功能,這類機制會定期將隨機化的 MAC 位址重新隨機化。使用
setMacRandomizationSetting
指定網路的隨機化層級。isPasspointTermsAndConditionsSupported()
:條款及細則是一項護照功能,可讓網路部署項目在設有安全的 Passpoint 網路中,取代使用開放式網路的不安全網頁認證入口。在需要接受條款及細則的情況下,系統會向使用者顯示通知。如果應用程式建議受條款及細則管制的 Passpoint 網路,必須先呼叫這個 API,確認裝置支援該項功能。如果裝置不支援這項功能,就無法連線至這個網路,且必須建議採用替代網路或舊版網路。isDecoratedIdentitySupported()
:向具有前置字串裝飾的網路進行驗證時,經過裝飾的身分前置字串可讓網路運算子更新網路存取 ID (NAI),以透過 AAA 網路內的多個 Proxy 執行明確轉送 (詳情請參閱 RFC 7542)。為符合 PPS-MO 擴充功能的 WBA 規格,Android 12 會實作這項功能。如果應用程式建議採用已裝飾的身分的 Passpoint 網路,必須先呼叫這個 API,以確保裝置支援這項功能。如果裝置不支援這項功能,就無法裝飾身分,且網路驗證可能會失敗。
如要建立 Passpoint 建議,應用程式必須使用 PasspointConfiguration
、Credential
和 HomeSp
類別。這些類別說明的是 Passpoint 設定檔,詳情請參閱 Wi-Fi Alliance Passpoint 規格。
下列程式碼範例說明如何為開放式、一種 WPA2、1 個 WPA3 網路和一個 Passpoint 網路提供憑證:
Kotlin
val suggestion1 = WifiNetworkSuggestion.Builder() .setSsid("test111111") .setIsAppInteractionRequired(true) // Optional (Needs location permission) .build(); val suggestion2 = WifiNetworkSuggestion.Builder() .setSsid("test222222") .setWpa2Passphrase("test123456") .setIsAppInteractionRequired(true) // Optional (Needs location permission) .build(); val suggestion3 = WifiNetworkSuggestion.Builder() .setSsid("test333333") .setWpa3Passphrase("test6789") .setIsAppInteractionRequired(true) // Optional (Needs location permission) .build(); val passpointConfig = PasspointConfiguration(); // configure passpointConfig to include a valid Passpoint configuration val suggestion4 = WifiNetworkSuggestion.Builder() .setPasspointConfig(passpointConfig) .setIsAppInteractionRequired(true) // Optional (Needs location permission) .build(); val suggestionsList = listOf(suggestion1, suggestion2, suggestion3, suggestion4); val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager; val status = wifiManager.addNetworkSuggestions(suggestionsList); if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { // do error handling here } // Optional (Wait for post connection broadcast to one of your suggestions) val intentFilter = IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION); val broadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (!intent.action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) { return; } // do post connect processing here } }; context.registerReceiver(broadcastReceiver, intentFilter);
Java
final WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion.Builder() .setSsid("test111111") .setIsAppInteractionRequired(true) // Optional (Needs location permission) .build(); final WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion.Builder() .setSsid("test222222") .setWpa2Passphrase("test123456") .setIsAppInteractionRequired(true) // Optional (Needs location permission) .build(); final WifiNetworkSuggestion suggestion3 = new WifiNetworkSuggestion.Builder() .setSsid("test333333") .setWpa3Passphrase("test6789") .setIsAppInteractionRequired(true) // Optional (Needs location permission) .build(); final PasspointConfiguration passpointConfig = new PasspointConfiguration(); // configure passpointConfig to include a valid Passpoint configuration final WifiNetworkSuggestion suggestion4 = new WifiNetworkSuggestion.Builder() .setPasspointConfig(passpointConfig) .setIsAppInteractionRequired(true) // Optional (Needs location permission) .build(); final List<WifiNetworkSuggestion> suggestionsList = new ArrayList<WifiNetworkSuggestion> {{ add(suggestion1); add(suggestion2); add(suggestion3); add(suggestion4); }}; final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); final int status = wifiManager.addNetworkSuggestions(suggestionsList); if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { // do error handling here… } // Optional (Wait for post connection broadcast to one of your suggestions) final IntentFilter intentFilter = new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION); final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (!intent.getAction().equals( WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) { return; } // do post connect processing here... } }; context.registerReceiver(broadcastReceiver, intentFilter);
應用程式首次提出建議後,系統會立即通知使用者。通知類型取決於裝置上執行的 Android 版本:
- 在 Android 11 (API 級別 30) 以上版本中,如果應用程式在前景執行,使用者會看到對話方塊;如果應用程式在背景執行,使用者還會看到通知。
- 在 Android 10 (API 級別 29) 中,無論應用程式是在前景或背景執行,使用者都會看到通知。
當平台連線到其中一個網路建議時,設定會顯示文字,將網路連線歸因於對應的建議應用程式。
處理使用者中斷連線
如果使用者連線時使用 Wi-Fi 挑選器來明確中斷連線,則當該網路仍位於有效範圍內時,系統會忽略該網路。在這段期間內,即使應用程式移除了並重新新增與網路對應的網路建議,也不會考慮自動連線。如果使用者使用 Wi-Fi 挑選器明確連線至先前中斷連線的網路,系統會立即將該網路視為自動連線。
變更應用程式的核准狀態
使用者拒絕網路建議通知後,系統會從應用程式中移除 CHANGE_WIFI_STATE
權限。使用者之後可以依序前往 Wi-Fi 控制項選單 (依序點選「設定」>「應用程式和通知」>「特殊應用程式存取權」>「Wi-Fi 控制」>「App name」),授予這項核准。