
Android 12 及以上系统限制了直接通过 TelephonyManager.createForSubscriptionId() 控制通话 SIM 卡的能力,需结合隐式 Intent 的厂商特定 extra 参数(如 "com.android.phone.extra.slot")实现免交互的双卡选卡拨号。
android 12 及以上系统限制了直接通过 `telephonymanager.createforsubscriptionid()` 控制通话 sim 卡的能力,需结合隐式 intent 的厂商特定 extra 参数(如 `"com.android.phone.extra.slot"`)实现免交互的双卡选卡拨号。
在 Android 12(API 级别 31)及更高版本中,系统出于隐私与安全考虑,移除了 TelephonyManager.createForSubscriptionId() 对 Intent.ACTION_CALL 的实际生效能力——即使你正确获取了 SubscriptionId 并创建了对应实例,startActivity(callIntent) 仍会默认使用系统设定的“默认语音 SIM”,而不会按预期走指定卡槽。这与 SMS(可通过 SmsManager.getSmsManagerForSubscriptionId() 完全控制)的行为有本质区别。
✅ 正确解法:依赖 Intent Extra 的厂商兼容方案
目前主流 OEM(如 Samsung、Xiaomi、OPPO、vivo、Realme 等)在处理 ACTION_CALL 时,普遍支持以下两个通用 extra 字段来显式指定 SIM 卡槽索引(0 或 1):
callIntent.putExtra("com.android.phone.extra.slot", simSlotIndex); // 高通/三星系常用
callIntent.putExtra("simSlot", simSlotIndex); // 联发科/部分国产厂商常用⚠️ 注意事项:
- 这些字段非 Android 官方 API,无文档保障,但已被广泛适配,实测在 Android 11–14 主流机型上稳定有效;
-
simSlotIndex必须为0或1(部分三卡设备支持2),超出范围将被忽略; -
必须在
startActivity()前设置,且不能与FLAG_ACTIVITY_NEW_TASK冲突(你的代码中已正确设置); - 需确保已动态申请
Manifest.permission.CALL_PHONE权限(Android 6.0+ 运行时权限),否则startActivity()将静默失败; - 某些定制 ROM(如华为 EMUI/HarmonyOS)可能完全屏蔽非默认 SIM 的自动拨号,此时需引导用户手动设置默认语音卡或改用
ACTION_DIAL(仅跳转拨号界面,不自动拨打)。
? 推荐优化后的调用逻辑(精简关键路径):
YZTurboWebAndroid 高性能 Android WebView 容器 SDK 接入。用于在 Android 项目中集成 WebView 容器,实现: (1) WebView 预加载与复用,提升 H5 页面加载速度 (2) 离线包管理,拦截请求优先命中本地资源 (3) JS Bridge 双向通信,Na...
Uri uri = Uri.parse("tel:" + Uri.encode(phoneNumber)); // 注意对号码做 URI 编码,防特殊字符
Intent callIntent = new Intent(Intent.ACTION_CALL, uri);
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 关键:注入 SIM 卡槽标识(兼容多厂商)
callIntent.putExtra("com.android.phone.extra.slot", simSlotIndex);
callIntent.putExtra("simSlot", simSlotIndex);
if (context.getPackageManager().resolveActivity(callIntent, 0) != null) {
context.startActivity(callIntent);
callback.invoke(); // 成功
} else {
callback.invoke("Error: No dialer app found or SIM slot not supported.");
}? 补充验证建议:
- 使用
SubscriptionManager.getActiveSubscriptionInfoList()先确认目标simSlotIndex是否真实存在且启用; - 在
else分支中可 fallback 到Intent.ACTION_DIAL(带tel:URI),并提示用户手动点击拨打,提升兼容性; - 不要依赖
telephonyManager.createForSubscriptionId()处理通话逻辑——它对ACTION_CALL无效,仅适用于查询类操作(如获取 IMSI、信号强度等)。
总结:在 Android 12+ 实现指定 SIM 拨号,核心不是「切换 TelephonyManager 实例」,而是「向拨号 Intent 注入厂商认可的 slot 标识」。这是当前最可靠、兼容性最佳的实践方案。

















