發表時間:2019-10-20git
本文會給出在 Android 上獲取運營商的方法,幾個相近方法結果的差別,以及在多卡狀況下有效的獲取方式。最後額外提一下一種不須要請求設備識別碼獲取運營商信息的方法。提供可運行的 demo 源碼。github
首先介紹一下這兩個碼,也是獲取運營商所必須的。bash
MCC,Mobile Country Code,移動設備國家代碼。MNC,Mobile Network Code,移動設備網絡代碼。MCC 和 MNC 串在一塊兒後,能夠用來表示惟一的移動設備運營商。我國的 MCC 是 460,MNC 則會出現一個運營商擁有多個的狀況,好比聯通有 0一、0六、09。當前的碼錶能夠在這個維基頁面找到。網絡
因而能夠先根據碼錶來構建這麼一個類:ui
enum class NetworkOperator(val opName: String) {
Mobile("移動"),
Unicom("聯通"),
Telecom("電信"),
Tietong("鐵通"),
Other("其餘");
companion object {
/** * 根據 [code](MCC+MNC) 返回運營商 */
fun from(code: Int) = when (code) {
46000, 46002, 46004, 46007, 46008 -> Mobile
46001, 46006, 46009 -> Unicom
46003, 46005, 46011 -> Telecom
46020 -> Tietong
else -> Other
}
fun fromOpName(name: String) = when (name) {
"移動" -> Mobile
"聯通" -> Unicom
"電信" -> Telecom
"鐵通" -> Tietong
else -> Other
}
}
}
複製代碼
你極可能也知道存在一個叫作 IMSI 的識別碼(注意並非 IMEI 哦)。國際移動用戶識別碼(International Mobile Subscriber Identity)能夠在蜂窩網絡中區分不一樣用戶,它是由 MCC、MNC 和 MSIN(移動訂戶識別碼,Mobile Subscription Identification Number)組成的。即 IMSI = MCC + MNC + MSIN。spa
在 Android 上首先須要請求 READ_PHONE_STATE
權限,而後經過 TelephonyManager 相關方法來獲取信息。TelephonyManager 有若干相近的方法,也讓人挺困惑的。Demo 裏會列出各個方法的結果,有興趣的能夠自行嘗試一下。.net
val tm = getSystemService<TelephonyManager>()
val text = """ TelephonyManager.getSimOperator(): ${tm.simOperator} TelephonyManager.getSimOperatorName(): ${tm.simOperatorName} TelephonyManager.getNetworkOperator(): ${tm.networkOperator} TelephonyManager.getNetworkOperatorName(): ${tm.networkOperatorName} TelephonyManager.getSubscriberId(): ${tm.subscriberId} Operator name: ${NetworkOperator.from(Integer.valueOf(tm.simOperator)).opName} """.trimIndent()
複製代碼
在個人設備上獲得的結果以下:code
TelephonyManager.getSimOperator(): 46009 // 當前流量卡,聯通
TelephonyManager.getSimOperatorName(): CMCC // 聯通
TelephonyManager.getNetworkOperator(): 46000 // 移動,卡一
TelephonyManager.getNetworkOperatorName(): CHINA MOBILE // 移動
TelephonyManager.getSubscriberId(): 46002326951xxxx // 移動,這就是 IMSI,xxxx 部分是由我隱去的
Operator name: 聯通
複製代碼
那麼獲得了 MCC+MNC,就能夠判斷出運營商了。ip
若是設備有雙卡,該怎麼樣呢?切換流量卡後再來看一下結果:資源
TelephonyManager.getSimOperator(): 46002 // 當前流量卡,移動
TelephonyManager.getSimOperatorName(): CMCC // 聯通,跟 getSimOperator() 結果不符
TelephonyManager.getNetworkOperator(): 46000 // 移動
TelephonyManager.getNetworkOperatorName(): CHINA MOBILE // 移動
TelephonyManager.getSubscriberId(): 46002326951xxxx // 移動
Operator name: 移動
複製代碼
經過嘗試能夠發現,TelephonyManager.getSimOperator()
方法得到的結果是根據當前設置的流量卡變化的。而其餘的方法結果都沒有變化,甚至獲得的信息也是不統一的,能夠說沒什麼用處。
不過我還沒法肯定這些方法的結果在不一樣設備不一樣 ROM 上的效果,僅供參考。能夠下載 demo 來查看在本身設備上的結果。
咱們都知道 Android 會根據設備設置的不一樣,去加載不一樣的資源文件夾。最典型的,會根據系統的語言去加載不一樣語言的字符串資源。而 Android 也能夠根據 MCC 和 MNC 加載不一樣的資源。
因而我靈光一閃,給 values
文件夾加上 -mcc460-mnc00
後綴,而後在裏面放上對應運營商的名字字符串,就能夠繞開權限獲取到運營商了。
不過等等,這麼一來要給每一個 MNC 都寫一個文件夾,還挺麻煩的,仍是用代碼來獲取吧:
val mcc = resources.configuration.mcc
val mnc = resources.configuration.mnc
val operator = NetworkOperator.from(mcc * 100 + mnc)
複製代碼
這個方法也是有缺點的,否則我就把這個方法寫在前了——沒法獲取到當前流量卡的信息,獲取到的信息是固定的。
運行如下命令來得到 demo 的源代碼:
git clone -b sim-operator https://github.com/Loong-T/demo.git
複製代碼