Android 6.0 及更高版本为特权应用推出了一项功能,可以为相应平台提供运营商专属配置。此功能是以 Android 5.1 (Lollipop MR1) 中推出的 UICC 运营商权限为基础,使运营商配置得以废弃静态配置叠加层,并使运营商和原始设备制造商 (OEM) 能够通过指定接口向相应平台动态提供运营商配置。
经过正确签名的运营商应用可以预加载到系统映像中,也可以自动安装,或者通过应用商店手动安装。应用会应平台的问询提供设置的配置信息,其中包括:
- 漫游/非漫游网络
- 可视语音信箱
- 短信/彩信网络设置
- VoLTE/即时通讯配置
返回值的选择完全取决于运营商应用,并且可以根据通过平台传递给应用的详细信息做出动态抉择。
这种方法的主要优点包括:
- 动态配置 - 支持非 MCCMNC 衍生的配置等概念,例如:移动虚拟网络运营商 (MVNO) 或客户选择使用的额外服务。
- 支持通过任何渠道销售的设备 - 例如,开放市场手机可以通过从应用商店下载应用,自动配置正确的设置。
- 安全性 - 仅向运营商签名的应用授予提供此配置的权限。
- 定义的 API - 过去,此配置主要存储在框架内的内部 XML 叠加层中,而不是通过公共 API 进行配置。Android 6.0 中的运营商配置 API 是公共的且进行了明确定义。
工作原理
加载配置
此功能提供的运营商配置是一组可以改变平台中各种电话相关行为的键值对。
适用于特定设备的那组值是通过依序查询以下组件来确定:
- 运营商应用(虽然这不是必需的,但对于 Android 开源项目 [AOSP] 之外的其他配置来说,建议进行征询)
- 与系统映像捆绑在一起的平台配置应用
- 硬编码到框架中(相当于 Android 6.0 之前的行为)的默认值
平台配置应用
通用的平台配置应用会与系统映像捆绑在一起。此应用能够提供常规运营商应用不会提供的变量的值。平台配置应用可在 packages/apps/CarrierConfig
(Android 6.0 中)找到
此应用的目的是在未安装运营商应用的情况下提供一些基于运营商网络的配置,运营商/OEM 应在他们自己的映像中仅对配置进行很小的改动。不过,运营商应该提供单独的运营商应用以实现运营商定制,从而使更新可以通过诸如应用商店之类的渠道分发给用户。
如何向运营商应用授予权限
根据 UICC 运营商权限中的记录,相关的运营商应用必须使用在 SIM 卡上发现的同一证书进行签名。
向运营商应用传递的信息
对运营商应用提供以下值,以使运营商应用能够对要返回的值做出动态抉择:
- MCC
- MNC
- SPN
- IMSI
- GID1
- GID2
- 运营商 ID
如需详细了解如何集成运营商 ID,请参阅将运营商 ID 与运营商配置集成。
在加载运营商配置时发生
在以下情况下,将构建键值对列表:
- 加载 SIM 卡(启动或 SIM 卡热插拔)时
- 运营商应用手动触发重新加载时
- 运营商应用更新时
如需了解详情,请参阅 android.service.carrier.CarrierService#onLoadConfig()
参考文档。
使用配置
构建配置后,配置中包含的值将用于设置系统配置中的各种值,其中包括:
- 内部框架电话设置
- SDK 返回的配置值,例如:在 SmsManager 中
- 应用设置,例如:拨号器中的 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 已重命名,更易于辨识。下表列出了已废弃的 API 和 Android 15 中引入的已重命名的 API:
已废弃(Android 14 或更低版本) | 等效版本 (Android 15 或更高版本) |
---|---|
TelephonyManager.isVoiceCapable() |
TelephonyManager.isDeviceVoiceCapable() |
TelephonyManager.isSmsCapable() |
TelephonyManager.isDeviceSmsCapable() |