关于Android获取运营商的文章已经很多,大部分都是没有深入测试,在双卡设备上存在读取错误信息的问题,这里给出总结。

首先是读取SIM卡权限的问题

注册

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

动态获取 读SIM卡的权限

在动态获取SIM卡权限时,这里的权限弹窗提示特别让人恶心,总是听人吐槽:一个视频播放软件,要什么拨打电话权限!!!需要一个友好的引导提示。

判断是否拥有读取SIM卡权限:

if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {}

存在误导的API

如果你百度获取SIM卡的运营商时,一般都会看到这个getNetworkOperator函数。从函数名上来看,确认了名称,注定要入坑。如果在双卡设备上反复测试,你就会怀疑这是什么鬼函数名,不按预期变化。事实上,这里的Network是蜂窝移动网络,不是万维网的数据流量。毕竟在手机出现之初期,只有打电话的能力,而且全部的移动设备本身就组织成了一个复杂的通话网络。所以,这里的getNetworkOperator是获取默认通话的运营商而已。

较为靠谱API

getSimOperator能获取到上网卡的运营商。
从函数名上,很难想象出,这个函数是在读取上网卡信息,能准确获取到上网卡的运营商。

android-20 源码

    /*** Returns the MCC+MNC (mobile country code + mobile network code) of the* provider of the SIM. 5 or 6 decimal digits.* <p>* Availability: SIM state must be {@link #SIM_STATE_READY}** @see #getSimState*/public String getSimOperator() {return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);}

android-21 源码

    /*** Returns the MCC+MNC (mobile country code + mobile network code) of the* provider of the SIM. 5 or 6 decimal digits.* <p>* Availability: SIM state must be {@link #SIM_STATE_READY}** @see #getSimState*/public String getSimOperator() {long subId = getDefaultSubscription();Rlog.d(TAG, "getSimOperator(): default subId=" + subId);return getSimOperator(subId);}

利用getSimOperator获取上网卡运营商的调用如下:

public static CarrierType getCarrierTypeAsFarAsPossible() {Context context = getApplication();if (context != null) {TelephonyManager telManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);if (telManager == null) {return CarrierType.UNKNOWN;}String operator = telManager.getSimOperator();if (operator != null) {return parseOperatorCode(operator);}}return CarrierType.UNKNOWN;}public static CarrierType parseOperatorCode(String operatorCode) {if (operatorCode == null || "".equals(operatorCode)) return UNKNOWN;switch (operatorCode) {case "46000":case "46002":case "46007":case "46008":return MOBILE;case "46001":case "46006":case "46009":return UNICOM;case "46003":case "46005":case "46011":return TELECOM;}return UNKNOWN;}

另一个存在误导的API

在上述的getSimOperator中,成功的获取了运营的operatorCode,这里的code是5数字的字符串,并不是运营商直接给出的名称。
那什么是运营商给出的名称呢?看下图:

那如何获取这个运营商下发的名称呢?有一个API是getSimOperatorName,又是一个确认过名称,注定要入坑的API。这个函数看着像是获取上网卡的运营商名称,实际获取的是默认打电话的运营商名称,与getNetworkOperator变化是同样的规律。

比较推荐的方式是getSimOperator获取到operatorCode,再判断移动联通电信。
运营商直接给出的名称会非常的乱,以联通为例,可能会有CUCC、UNICOM、中国联通、中国联通 3G、中国联通 4G等等,非常个性,不可预测,取决于当地运营商大佬想干嘛就干嘛。

如何精确获取上网卡运营商

分系统版本来看待双卡

官方文档只支持5.1及其之后的系统提供双卡API。对于之前的系统版本,目前的市场占比已经很少了。采用的策略是放弃不支持的机器,因为这边对精度要求非常高,可以判断不出来运营商,但不能判断出错。

5.0及其之前 android.os.Build.VERSION.SDK_INT<=21

这部分放弃,将其归入没有获取到系统权限的一样,当做读不出运营商看待。

5.1及其之后 android.os.Build.VERSION.SDK_INT>=22

精准获取上网卡运营商的调用如下:

    public static CarrierType getCurrentCarrierType() {if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {return UNKNOWN;}Context context = getApplication();if (context == null) {return UNKNOWN;}TelephonyManager telMag = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);if (telMag == null) {return UNKNOWN;}return parseOperatorCode(telMag.getSimOperator());}public static CarrierType parseOperatorCode(String operatorCode) {if (operatorCode == null || "".equals(operatorCode)) return UNKNOWN;switch (operatorCode) {case "46000":case "46002":case "46007":case "46008":return MOBILE;case "46001":case "46006":case "46009":return UNICOM;case "46003":case "46005":case "46011":return TELECOM;}return UNKNOWN;}

注意

getNetworkOperator不是获取上网卡运营商
getSimOperatorName不是获取上网卡运营商的名称

获取默认通话、默认信息卡

关于获取默认通话的SIM卡

获取默认通话的SIM卡,基本上,大量API都是获取默认通话SIM卡的。在Android5.1之前的版本中,只能获取到默认通话SIM,在Android5.1及其之后,可以用getDefaultVoiceSubscriptionInfo获取到默认通话SIM卡信息。

关于获取默认发信息的SIM卡

在Android5.1及其之后,用getDefaultSmsSubscriptionInfo可以获取到。同样,这是个被隐藏的方法,需要反射。

默认上网卡信息

在5.1及其之后,用getDefaultDataSubscriptionInfo可以获取到,也需要反射才行。

Android双卡设备 如何正确获取上网卡运营商类型相关推荐

  1. Android获取手机运营商名称

    前言 因为项目中经常会遇到要上传一系列设备信息的功能,为了方便使用,所以就拆分成以下系列文章来单独介绍如何获取各类设备信息 手机运营商获取 AndroidID.IMEI.OAID获取 地理位置信息经纬 ...

  2. android获取各运营商信号,一篇关于 Android 获取运营商的全面笔记

    发表时间:2019-10-20 内容总览 本文会给出在 Android 上获取运营商的方法,几个相近方法结果的差异,以及在多卡情况下有效的获取方式.最后额外提一下一种不需要请求设备识别码获取运营商信息 ...

  3. Android 获取手机运营商、有无sim卡

    名词解释 MCC Mobile Country Code:移动国家代码,由3位数字组成,唯一地识别移动用户所属的国家.MCC由国际电联(ITU)统一分配和管理,一旦分配就不可更改.所以一个MCC只能对 ...

  4. 正确地获取手机运营商

    通常的做法都是通过CTTelephonyNetworkInfo来做判断.但是在实际应用的时候,发现在双卡iPhone上会有bug,并不能正确地获取到运营商信息.所以,在前人的轮子基础上,改造了一下. ...

  5. android sim卡分析,Android 判断SIM卡属于哪个移动运营商详解及实例

    Android 判断SIM卡属于哪个移动运营商 第一种方法: 获取手机的IMSI码,并判断是中国移动\中国联通\中国电信 TelephonyManager telManager = (Telephon ...

  6. PHP 获取手机号运营商

    1. 前言 公司有一个话费充值项目,需要获取手机号的运营商,进行执行不同的逻辑. 根据手机号的前三位就可以知道手机号的运营商 移动:134.135.136.137.138.139.150.151.15 ...

  7. iphone 获取手机运营商信息

    获取手机运营商信息是通过获取imsi来判断的,它是有一个自己的标准和规则的,下面先介绍一下imsi: IMSI: 国际移动用户识别码(IMSI:International Mobile Subscri ...

  8. iOS判断运营商类型

    一.获取运营类型 1.需要导入两个头文件 #import <CoreTelephony/CTCarrier.h> #import <CoreTelephony/CTTelephony ...

  9. 介绍一种Android 平台 不需要获取imei imsi 无权限就能获取手机运营商的方法

    demo 链接:https://github.com/miqt/GetOperator 先贴一下需要权限,然后通过获取 imsi 根据前缀判断运营商的方法: if (checkPermission(c ...

最新文章

  1. 十步完全理解 SQL
  2. MySQL 主从架构配置详解
  3. VisualSVN server 无法启动
  4. Hibernate - DetachedCriteria 的完整用法
  5. 全面认识 RUST -- 掌控未来的雷电
  6. 算法 摩尔投票算法(图解例题)
  7. android释放全局变量,Android全局变量
  8. 一些常用的google scholar网站
  9. 遍历一个List的几种方法
  10. html 动态导航菜单,导航菜单,css3,javascript,响应式菜单,html,css
  11. 目标跟踪(4)使用dlib进行对象跟踪
  12. pytorch GPU和CPU模型相互加载
  13. 高德地图定位 地图比例缩放
  14. 美国大学倒闭危机!1/4高校或将破产,清华本科留学率下降
  15. 站在讲台上的时候,我怕我会心虚
  16. Java简单实现猜拳游戏
  17. 【学习笔记】STC校验子格编码 syndrome-trellis code
  18. php trimarray,PHP trim()函数和array_unique()函数去重 【原创】
  19. SQL语句查询电影评分案例分析
  20. 硬件大熊原创合集(2023/02更新)

热门文章

  1. Nginx图片服务器访问图片404
  2. 每次进入命令需要重新source的解决方法
  3. Windows驱动_WSK驱动之二WSK的操作
  4. Java习题练习:和尚挑水
  5. 一个让我用得很爽的个性导航h2w1.com
  6. 13c语言——运算符
  7. vsftpd2.3.4笑脸漏洞
  8. gitlab显示500 Whoops, something went wrong on our end
  9. Docker工具之Daocloud的使用
  10. chromedriver下载与安装方法