發(fā)表時間:2019-10-20
內容總覽
本文會給出在 Android 上獲取運營商的方法道伟,幾個相近方法結果的差異来破,以及在多卡情況下有效的獲取方式钝尸。最后額外提一下一種不需要請求設備識別碼獲取運營商信息的方法。提供可運行的 demo 源碼愉粤。
MCC 和 MNC
首先介紹一下這兩個碼暇务,也是獲取運營商所必須的泼掠。
MCC,Mobile Country Code般卑,移動設備國家代碼武鲁。MNC,Mobile Network Code蝠检,移動設備網絡代碼沐鼠。MCC 和 MNC 串在一起后,可以用來表示唯一的移動設備運營商叹谁。我國的 MCC 是 460饲梭,MNC 則會出現一個運營商擁有多個的情況,比如聯(lián)通有 01焰檩、06憔涉、09。當前的碼表可以在這個維基頁面找到析苫。
于是可以先根據碼表來構建這么一個類:
enum class NetworkOperator(val opName: String) {
Mobile("移動"),
Unicom("聯(lián)通"),
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
"聯(lián)通" -> Unicom
"電信" -> Telecom
"鐵通" -> Tietong
else -> Other
}
}
}
你很可能也知道存在一個叫做 IMSI 的識別碼(注意并不是 IMEI 哦)兜叨。國際移動用戶識別碼(International Mobile Subscriber Identity)可以在蜂窩網絡中區(qū)分不同用戶穿扳,它是由 MCC、MNC 和 MSIN(移動訂戶識別碼国旷,Mobile Subscription Identification Number)組成的矛物。即 IMSI = MCC + MNC + MSIN。
如何獲取
在 Android 上首先需要請求 READ_PHONE_STATE
權限跪但,然后通過 TelephonyManager 相關方法來獲取信息履羞。TelephonyManager 有若干相近的方法,也讓人挺困惑的屡久。Demo 里會列出各個方法的結果忆首,有興趣的可以自行嘗試一下。
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()
在我的設備上得到的結果如下:
TelephonyManager.getSimOperator(): 46009 // 當前流量卡被环,聯(lián)通
TelephonyManager.getSimOperatorName(): CMCC // 聯(lián)通
TelephonyManager.getNetworkOperator(): 46000 // 移動糙及,卡一
TelephonyManager.getNetworkOperatorName(): CHINA MOBILE // 移動
TelephonyManager.getSubscriberId(): 46002326951xxxx // 移動,這就是 IMSI蛤售,xxxx 部分是由我隱去的
Operator name: 聯(lián)通
那么得到了 MCC+MNC丁鹉,就可以判斷出運營商了妒潭。
雙卡情況
如果設備有雙卡悴能,該怎么樣呢?切換流量卡后再來看一下結果:
TelephonyManager.getSimOperator(): 46002 // 當前流量卡雳灾,移動
TelephonyManager.getSimOperatorName(): CMCC // 聯(lián)通漠酿,跟 getSimOperator() 結果不符
TelephonyManager.getNetworkOperator(): 46000 // 移動
TelephonyManager.getNetworkOperatorName(): CHINA MOBILE // 移動
TelephonyManager.getSubscriberId(): 46002326951xxxx // 移動
Operator name: 移動
通過嘗試可以發(fā)現,TelephonyManager.getSimOperator()
方法獲得的結果是根據當前設置的流量卡變化的谎亩。而其他的方法結果都沒有變化炒嘲,甚至得到的信息也是不統(tǒng)一的,可以說沒什么用處匈庭。
不過我還無法確定這些方法的結果在不同設備不同 ROM 上的效果夫凸,僅供參考≮宄郑可以下載 demo 來查看在自己設備上的結果夭拌。
不需要權限的方法
我們都知道 Android 會根據設備設置的不同,去加載不同的資源文件夾衷咽。最典型的鸽扁,會根據系統(tǒng)的語言去加載不同語言的字符串資源。而 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 源代碼
運行以下命令來獲得 demo 的源代碼:
git clone -b sim-operator https://github.com/Loong-T/demo.git