Android 12(API 31)指定SIM卡索引发起无交互通话问题求助
指定SIM卡槽无人工交互拨号问题解决方案
问题描述
我需要实现无人工交互的拨打电话功能,通过Socket传递电话号码与SIM卡槽索引。当前未设置默认SIM时会弹出SIM选择弹窗,设置默认SIM则仅通过默认SIM拨号,但我希望能指定任意SIM卡槽索引发起通话。该方案在短信功能上可行,但通话功能无法实现,以下是我的代码:
@ReactMethod public void makeCallWithSim(int simSlotIndex, String phoneNumber, Callback callback) { Context context = getReactApplicationContext(); TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (telephonyManager == null) { // TelephonyManager is not available, handle error if (callback != null) { callback.invoke("TelephonyManager is not available."); } return; } SubscriptionManager subscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); if (subscriptionManager == null) { // SubscriptionManager is not available, handle error if (callback != null) { callback.invoke("SubscriptionManager is not available."); } return; } // Get the active subscriptions List<SubscriptionInfo> activeSubscriptions = subscriptionManager.getActiveSubscriptionInfoList(); if (activeSubscriptions == null || activeSubscriptions.isEmpty()) { // No active subscriptions found, handle error if (callback != null) { callback.invoke("No active subscriptions found."); } return; } // Check if the device supports multiple SIM cards if (activeSubscriptions.size() < 2) { // Device does not support multiple SIM cards // Use the default SIM card for the call Log.d("Info", "In IF"); Uri uri = Uri.parse("tel:" + phoneNumber); Intent callIntent = new Intent(Intent.ACTION_CALL, uri); callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (callIntent.resolveActivity(context.getPackageManager()) != null) { context.startActivity(callIntent); if (callback != null) { callback.invoke(); // Call initiated successfully } } else { if (callback != null) { callback.invoke("Error: No activity found to handle the call intent."); } } } else { Log.d("Info", "In ELSE"); // Get the subscription ID for the given SIM slot // SubscriptionInfo subscriptionInfo = activeSubscriptions.get(simSlotIndex); SubscriptionInfo subscriptionInfo = subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlotIndex); int subscriptionId = subscriptionInfo.getSubscriptionId(); // Set the SIM subscription ID for the call telephonyManager = telephonyManager.createForSubscriptionId(subscriptionId); // Make the call using the specified SIM Uri uri = Uri.parse("tel:" + phoneNumber); Intent callIntent = new Intent(Intent.ACTION_CALL, uri); callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (callIntent.resolveActivity(context.getPackageManager()) != null) { context.startActivity(callIntent); if (callback != null) { callback.invoke(); // Call initiated successfully } } else { if (callback != null) { callback.invoke("Error: No activity found to handle the call intent."); } } } }
问题分析与修复方案
原代码核心问题在于:仅通过createForSubscriptionId创建TelephonyManager实例,但未将订阅ID关联到拨号Intent。Android的ACTION_CALL本身不支持直接指定SIM,需通过TelecomManager和PhoneAccountHandle实现指定卡槽拨号。
修复后的代码
@ReactMethod public void makeCallWithSim(int simSlotIndex, String phoneNumber, Callback callback) { Context context = getReactApplicationContext(); TelecomManager telecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); SubscriptionManager subscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); if (telecomManager == null) { callback.invoke("TelecomManager不可用"); return; } if (subscriptionManager == null) { callback.invoke("SubscriptionManager不可用"); return; } // 获取指定卡槽的活跃SIM信息 SubscriptionInfo subscriptionInfo = subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simSlotIndex); if (subscriptionInfo == null) { callback.invoke("指定卡槽无活跃SIM卡"); return; } // 获取SIM对应的PhoneAccountHandle PhoneAccountHandle phoneAccountHandle = telecomManager.getPhoneAccountHandleForSubscription(subscriptionInfo.getSubscriptionId()); if (phoneAccountHandle == null) { callback.invoke("无法获取指定SIM的PhoneAccount"); return; } // 构建拨号Intent并指定SIM卡 Uri uri = Uri.parse("tel:" + phoneNumber); Intent callIntent = new Intent(Intent.ACTION_CALL, uri); callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); callIntent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); if (callIntent.resolveActivity(context.getPackageManager()) != null) { context.startActivity(callIntent); callback.invoke(); // 拨号成功 } else { callback.invoke("无可用应用处理拨号请求"); } }
关键改动说明
- 替换
TelephonyManager为TelecomManager:Android 5.1(API 22)起,多SIM卡拨号逻辑迁移至TelecomManager,原TelephonyManager不再负责SIM选择控制。 - 添加
EXTRA_PHONE_ACCOUNT_HANDLE参数:将指定SIM对应的PhoneAccountHandle传入Intent,系统会直接使用该SIM发起通话,避免弹窗。 - 简化逻辑:直接通过卡槽索引获取目标SIM信息,减少冗余判断。
权限配置
在AndroidManifest.xml中添加必要权限,并确保运行时已动态授予:
<uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- Android 10及以上部分设备需要 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
内容的提问来源于stack exchange,提问作者Nabeel Sajid
相关产品推荐
相关产品推荐

