Android 6.0 以上版本含有具有特殊權限的應用程式,可以為平台提供電信業者專屬的設定。這項功能是以 Android 5.1 (Lollipop MR1) 中推出的 UICC 電信業者特權為基礎,可將電信業者設定移出靜態設定覆蓋層,並讓電信業者和原始設備製造商 (OEM) 透過定義的介面,動態地將電信業者設定提供給平台。
正確簽署的電信業者應用程式可以在系統映像檔中預先載入、自動安裝,或是透過應用程式商店手動安裝。平台會查詢應用程式,為設定提供設定,包括:
- 漫遊/非漫遊網路
- 視覺化語音信箱
- 簡訊/多媒體訊息網路設定
- VoLTE/IMS 設定
決定要傳回哪些值完全取決於電信業者應用程式,且可根據透過平台傳遞至應用程式的詳細資訊,以動態方式傳回。
這種做法的主要優點如下:
- 動態設定:支援非 MCCMNC 衍生設定的概念,例如行動虛擬網路營運商 (MVNO) 或客戶選擇加入額外服務。
- 支援透過任何管道銷售的裝置 - 舉例來說,只要從應用程式商店下載應用程式,開放市場手機就能自動設定正確的設定。
- 安全性:只有由電信業者簽署的應用程式,才有權提供這項設定。
- 已定義的 API:先前這項設定大多儲存在架構內部的內部 XML 重疊層,而不是透過公用 API 儲存。Android 6.0 中的電信業者設定 API 為公開且定義明確。
運作方式
載入設定
這項功能提供的電信業者設定是一組鍵/值組合,可變更平台中各種與電話相關的行為。
特定裝置的一組值是由依序查詢下列元件決定:
- 電信業者應用程式 (這是選用項目,但建議您在這個位置設定 Android 開放原始碼計畫 (AOSP) 以外的額外設定)
- 系統映像檔隨附的平台設定應用程式
- 預設值,已硬式編碼至架構中 (等同於 Android 6.0 之前的行為)
平台設定應用程式
系統映像檔已隨附通用平台設定應用程式。這個應用程式可為一般電信業者應用程式無法提供的任何變數提供值。您可以在 Android 6.0 中找到平台設定應用程式:packages/apps/CarrierConfig
這個應用程式的目的是在未安裝電信業者應用程式時,提供一些個別網路設定,電信業者/原始設備製造商應只在自家映像檔中對其進行最少的變更。電信業者應將單獨的電信業者應用程式提供電信業者自訂功能,以便透過應用程式商店等管道發布更新內容。
如何授予電信業者應用程式特殊權限
驗證的電信業者應用程式必須使用 SIM 卡上的憑證簽署,如 UICC 電信業者權限一文所述。
哪些資訊會傳送給電信業者應用程式
運營商應用程式會提供下列值,讓應用程式能動態決定要傳回哪些值:
- MCC
- MNC
- SPN
- IMSI
- GID1
- GID2
- 電信業者 ID
如要進一步瞭解如何整合電信業者 ID,請參閱 整合電信業者 ID 與 CarrierConfig。
載入電信業者設定時
鍵/值組合清單的結構如下:
- SIM 卡載入後 (開機或 SIM 卡熱交換)
- 電信業者應用程式手動觸發重新載入作業時
- 電信業者應用程式更新時
詳情請參閱 android.service.carrier.CarrierService#onLoadConfig()
參考資料。
使用設定
建構設定時,其中所含的值會用來設定系統設定的各種值,包括:
- 內部架構電話設定
- SDK 傳回的設定值,例如在 SmsManager 中
- 應用程式設定,例如 Dialer 中的 VVM 連線值
設定鍵
金鑰清單在 android.telephony.CarrierConfigManager
中是公開 SDK 的一部分,無法在相同的 API 級別中變更。如需金鑰的摘要,請參閱下表。
建構應用程式
建立應用程式
應用程式必須指定 Android 6.0 API 級別 (23)。
宣告覆寫 android.service.carrier.CarrierService 的類別
- 覆寫
onLoadConfig
,根據傳遞的service.carrier.CarrierIdentifier
物件傳回您要提供的值。 - 在可能隨時間變更的電信業者設定情況下 (例如使用者在帳戶中新增額外服務),請新增邏輯來呼叫
notifyConfigChangedForSubId
。
範例如下:
public class SampleCarrierConfigService extends CarrierService { private static final String TAG = "SampleCarrierConfigService"; public SampleCarrierConfigService() { Log.d(TAG, "Service created"); } @Override public PersistableBundle onLoadConfig(CarrierIdentifier id) { Log.d(TAG, "Config being fetched"); PersistableBundle config = new PersistableBundle(); config.putBoolean( CarrierConfigManager.KEY_CARRIER_VOLTE_AVAILABLE_BOOL, true); config.putBoolean( CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, false); config.putInt(CarrierConfigManager.KEY_VOLTE_REPLACEMENT_RAT_INT, 6); // Check CarrierIdentifier and add more config if needed… return config; } }
詳情請參閱 android.service.carrier.CarrierService
參考資料。
在資訊清單中命名類別
範例如下:
<service android:name=".SampleCarrierConfigService" android:label="@string/service_name" android:permission="android.permission.BIND_CARRIER_SERVICES"> <intent-filter> <action android:name="android.service.carrier.CarrierService"/></intent-filter> </service>
使用 SIM 卡上的相同憑證簽署應用程式
如需相關規定,請參閱「UICC 電信業者權限」。
透過電信業者應用程式新增 APN
如要透過程式輔助方式從電信業者應用程式新增 APN (例如在 SIM 卡啟用期間),請使用 ContentResolver
API 將 APN 項目新增至由 URI android.provider.Telephony.Carriers.CONTENT_URI
識別的內容供應器。如要進一步瞭解內容 URI 的資料表結構,請參閱「
Telephony.Carriers
」一節。
詳情請參閱「APN 和 CarrierConfig」。
測試應用程式
建構設定應用程式後,您可以使用以下方式測試程式碼:
- 內含有效憑證簽章的 SIM 卡
- 搭載 Android 6.0 以上版本的裝置,例如 Android 裝置
設定電信業者服務功能
在 Android 中,電信業者服務功能會說明裝置是否支援語音、訊息和資料服務。電信業者可以在裝置層級和訂閱層級 (Android 15 以上版本) 指定裝置的電信服務功能。
裝置層級服務功能
裝置層級服務功能會在裝置製造時設定 (製造後無法變更)。電信業者可以透過下列系統資源覆寫指定裝置層級功能:
應用程式可透過下列 API 查詢裝置層級服務功能:
訂閱層級的服務功能
對於搭載 Android 15 以上版本的裝置,電信業者可以在訂閱層級指定裝置的服務功能。如要指定訂閱層級的服務功能,請使用
CarrierConfigManager.KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY
API。舉例來說,如要指定訂閱項目僅限於資料,請將值設為
SubscriptionManager#SERVICE_CAPABILITY_DATA
。
應用程式 (預先載入的系統應用程式和第三方應用程式) 可以透過
SubscriptionInfo.getServiceCapabilities()
方法查詢指定訂閱項目的電信業者服務功能。如此一來,應用程式開發人員就能根據訂閱項目的可用功能,自訂應用程式的使用者體驗。舉例來說,如果使用者訂閱的是數據專用的訂閱項目,應用程式開發人員可以確保撥號應用程式不允許撥打電話。
已淘汰的服務功能 API
從 Android 15 開始,Android 會同時提供裝置層級和訂閱層級的服務功能。因此,我們重新命名現有的裝置層級功能 API,以便讀者更容易理解。下表列出 Android 15 中淘汰的 API 和重新命名的 API:
已淘汰 (Android 14 以下版本) | 對等 (Android 15 以上版本) |
---|---|
TelephonyManager.isVoiceCapable() |
TelephonyManager.isDeviceVoiceCapable() |
TelephonyManager.isSmsCapable() |
TelephonyManager.isDeviceSmsCapable() |