首先我们都知道如何获取Android手机的Sim手机号
fun getNativePhoneNumber(context: Context): String? {
val tm = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
return tm.line1Number
}
获取到 TelephonyManager 对象,通过调用 getLine1Number方法就可以获取到手机号;
注意:提前获取权限:
Manifest.permission.READ_PHONE_STATE: android 设备状态
那么获取双卡设备的第二张卡的手机号怎么办呢?
进到TelephonyManager的getLine1Number的方法源码中:
可以看到:getLine1Number方法是通过其内部的getLine1Number(getSubId)方法实现的,但是这个方法被注解标记:@UnsupportedAppUsage 不可被应用程序调用;
看到这里就会想:通过一个subId 通过getLine1Number方法就可以获取到手机号,而这个id大概率是每一个Sim卡所对应的唯一Id值;
通过反射调用内部getLine1Number(int subId) 方法
这个方法不可被调用,那就试试通过发射能不能调用到这个程序呢:
通过测试代码测试:发现真的可以通过反射调用到被@UnsupportedAppUsage 标记的方法;
获取subId值
解决了注解方法不可调用的问题,接下来解决获取subId的问题;
从上面的截图可以看到subId是通过一个 getSubId() 方法获取到的;
注意红框中的类:SubscriptionManager,大胆猜想,subId全称是不是就叫SubscriptionId,毕竟他是通过SubscriptionManager获取到的;
那么可以研究一下这个类:SubscriptionManager
创建方式:
SubscriptionManager subscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
并找到了下图中的方法:
该方法返回一个SubscriptionInfo列表,并且SubScriptionInfo对象存在一个getSubscriptionId()方法;
整个流程就是:
1、获取SubscriptionManager,通过其getActiveSubscriptionInfoList()方法获取到SubscriptionInfo列表;
2、遍历SubscriptionInfo列表,通过getSubscriptionId()方法获取获取到id值;
3、获取TelephonyManager类对象,通过反射传入id值;
4、method.invoke(tm, subId)方法的返回值就是手机号码;
End
这样就可以获取到多卡Android设备的所有可用Sim卡的手机号码;
列一下常用方法:
- 获取通讯类型:
- 获取网络类型:
- 获取蜂窝网络运营商:
-
运营商网段筛选:
fun from(code: String) = when (code) { "46000", "46002", "46004", "46007", "46008" -> Operator.CHINA_MOBILE "46001", "46006", "46009" -> Operator.CHINA_UNICOM "46003", "46005", "46011" -> Operator.CHINA_TELECOM "46020" -> Operator.CHINA_RAILCOM else -> Operator.UNKNOWN_OPERATOR } fun fromOpName(name: String) = when (name) { "中国移动" -> Operator.CHINA_MOBILE "中国联通" -> Operator.CHINA_UNICOM "中国电信" -> Operator.CHINA_TELECOM "中国铁通" -> Operator.CHINA_RAILCOM else -> Operator.UNKNOWN_OPERATOR } enum class Operator(var type: Int, var operatorName: String) { CLOSE_FLOW(-2, "流量数据未打开") , NONE_OPERATOR(-1, "无sim卡") , UNKNOWN_OPERATOR(0, "其他") , CHINA_MOBILE(1, "中国移动") , CHINA_UNICOM(2, "中国联通") , CHINA_TELECOM(3, "中国电信") , CHINA_RAILCOM(4, "中国铁通"); }
..........