如何获取双卡手机中通话所用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
相关产品推荐
相关产品推荐

