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

如何获取双卡手机中通话所用SIM卡的SIM ID?

你好!你提到的getSimSerialNumber()方法在单卡手机上没问题,但双卡场景下就需要针对当前通话的SIM卡来获取对应的序列号了。下面我会一步步给你讲清楚怎么实现,兼顾不同Android版本的兼容性:

首先,得明确几个关键点:

  • Android从5.1(API 22)开始正式支持双卡相关API,低版本系统可能没法完美适配
  • 需要申请对应的权限,还要处理动态权限请求
  • 要先获取所有激活的SIM卡信息,再结合通话状态找到当前使用的那一张

1. 权限准备

首先在AndroidManifest.xml里声明必要权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- Android 10及以上,可能需要额外申请READ_PHONE_NUMBERS或READ_SMS权限,具体看你的目标SDK版本 -->

Android 6.0(API 23)及以上还需要动态申请READ_PHONE_STATE权限,记得在代码里处理权限请求逻辑。

2. 获取所有激活的SIM卡信息

我们可以用SubscriptionManager来获取设备上所有激活的SIM卡详情,把它们的subscriptionId和simSerialNumber对应起来,方便后续查找:

// 初始化保存SIM信息的Map
private Map<Integer, String> simInfoMap = new HashMap<>();

private void loadAllSimInfo() {
    SubscriptionManager subscriptionManager = 
        (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
    
    if (subscriptionManager == null) {
        Log.e("SIM_INFO", "无法获取SubscriptionManager服务");
        return;
    }

    List<SubscriptionInfo> activeSubscriptions = subscriptionManager.getActiveSubscriptionInfoList();
    if (activeSubscriptions == null || activeSubscriptions.isEmpty()) {
        Log.d("SIM_INFO", "没有激活的SIM卡");
        return;
    }

    for (SubscriptionInfo info : activeSubscriptions) {
        String simSerial = info.getSimSerialNumber();
        int subscriptionId = info.getSubscriptionId();
        // 保存subscriptionId和SIM序列号的映射
        simInfoMap.put(subscriptionId, simSerial);
        Log.d("SIM_INFO", "SIM卡信息:ID=" + subscriptionId + ",序列号=" + simSerial);
    }
}

3. 监听通话状态,获取当前通话的SIM序列号

接下来我们需要监听通话状态,当通话开始时(CALL_STATE_OFFHOOK状态),获取当前通话对应的SIM卡信息:

private void setupCallStateListener() {
    TelephonyManager telephonyManager = 
        (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    
    PhoneStateListener phoneStateListener = new PhoneStateListener() {
        @Override
        public void onCallStateChanged(int state, String phoneNumber) {
            super.onCallStateChanged(state, phoneNumber);
            
            // 当通话处于接通状态时
            if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
                String currentSimSerial = null;
                
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    // Android 8.0及以上,直接获取当前活跃的SubscriptionId
                    int activeSubscriptionId = telephonyManager.getActiveSubscriptionId();
                    currentSimSerial = simInfoMap.get(activeSubscriptionId);
                } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
                    // Android 5.1到7.1,通过SubscriptionManager获取当前活跃的SIM信息
                    SubscriptionManager subscriptionManager = 
                        (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
                    SubscriptionInfo activeInfo = subscriptionManager.getActiveSubscriptionInfo();
                    if (activeInfo != null) {
                        currentSimSerial = activeInfo.getSimSerialNumber();
                    }
                }
                
                if (currentSimSerial != null) {
                    Log.d("SIM_INFO", "当前通话使用的SIM序列号:" + currentSimSerial);
                    // 这里可以把序列号用于你的业务逻辑
                } else {
                    Log.e("SIM_INFO", "无法获取当前通话的SIM序列号");
                }
            }
        }
    };
    
    // 注册通话状态监听
    telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}

注意事项

  • 版本兼容性:不同Android版本的API差异较大,一定要做好版本判断,避免崩溃
  • 权限问题:动态权限请求必须处理,否则会导致权限拒绝,无法获取SIM信息
  • 厂商差异:部分厂商可能对双卡API有自定义实现,建议在不同品牌的设备上测试
  • 空值判断:所有获取的对象(比如SubscriptionManager、SubscriptionInfo)都要做空值检查,防止空指针异常

内容的提问来源于stack exchange,提问作者Tabrez Ansari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:20:05