You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 03:21:07