1. 程式人生 > >android 獲取手機號

android 獲取手機號

原文出處 http://blog.csdn.net/r8hzgemq/article/details/7941274#comments

以下結論,只是本人親手測試的結果,可能並不全面:

最近做一個專案,需要取使用者手機號,用程式碼取獲取移動神州行的,返回null,但是取另外一個同事的聯通WCDMA,可以獲取到。很是糾結,想弄明白手機號碼到底存放在什麼地方,後來就去google了一下,很多熱心網友都給出了一個相同的回答:能取到手機號的是因為運營商將手機號寫入了SIM中,不能取到號碼的是需要通過SIM卡的串號IMSI上行到運營商,然後通過對映表中查詢對應的手機號。當時這麼一聽,覺得挺有道理,就信了。

後來和ios開發的同事聊起這事兒,他說iphone手機只要一插入卡,過幾秒鐘就能讀出來手機號。親自給我演示了一下,果然如此,原來iphone也是上行imsi到運營商,然後去拿到手機號的。

回到android這邊,我想啊,android原本可以取到手機號的卡,如果不讓android手機IMSI上行,不知道能不能取到手機號。如果能,說明手機號真的存在sim卡中,如果不能,說明即使能取到號碼的sim卡,裡面也並沒有儲存手機號,只是運營商能返回這個sim卡對應的手機號,而那些取不到手機號的sim卡,也將imsi上行給了運營商,而運營商不返回給終端手機號碼。後來我就把手機調成飛航模式,再執行程式碼,果然不出所料,所有手機都取不到號碼了。。看來SIM卡里並沒有存放手機號,起碼我上面測試過的2種卡沒有存,其他的大家一起測測吧。

那新的疑問就出來了,我們打電話的時候,被叫是怎麼知道主叫的手機號的呢。

其實是終端將自己的IMSI串號和被叫手機號一起上行到運營商,運營商通過主叫的IMSI查詢到手機號,通過被叫到手機號查詢到IMSI串號(找不到的話會提示主叫,撥打的是空號)。然後通過被叫到串號IMSI查詢到對應的被叫手機,並將主叫的手機號下行給了被叫,這也就是為什麼我們可以擷取到來電號碼原因了。

相關程式碼供參考

1獲取手機號(不是每個SIM卡都可以獲取到。再次更正很多網友的一個觀點。其實手機號並沒有儲存在SIM中,即使能拿到手機號的SIM卡也沒有儲存手機號)

  1. String telephoneNumber = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE).getLine1Number();  
  1. <uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/>


2獲取來電號碼(每個SIM都可以,因為運營商將主叫的IMSI查詢到對應手機號碼後,一起下行給了被叫。否則我們就不知道是誰的來電了)
在配置檔案中註冊廣播

  1. <receiverandroid:name=".broadcast.PhoneStatReceiver">
  2.    <intent-filter>
  3.     <actionandroid:name="android.intent.action.PHONE_STATE"/>
  4.     <actionandroid:name="android.intent.action.NEW_OUTGOING_CALL"/>
  5.    </intent-filter>
  6.   </receiver>


加幾個許可權

  1. <uses-permissionandroid:name="android.permission.CALL_PHONE"/>
  2. <uses-permissionandroid:name="android.permission.CALL_PRIVILEGED"/>
  3. <uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/>
  4. lt;uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>


然後在java程式碼廣播類中的onReceive()方法中如下:

  1. @Override
  2.  publicvoid onReceive(Context context, Intent intent) {  
  3. String out_phoneNum = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);  
  4.   String in_phoneNum = intent.getExtras().getString("incoming_number");  
  5.   Logger.out(1"撥出去的號碼-->" + out_phoneNum + "---來電號碼-->" + in_phoneNum);  
  6. }   


 如果專案中非要用到使用者的真實手機號,有一個很麻煩的辦法可以做到:

首先嚐試著取client手機號,取不到時由client後臺將當前系統時間發一條簡訊到“phoneService”,同時由http或者udp傳送到“pcService”,"phoneService"提取出簡訊的發件人手機號和簡訊內容(System.currentTimeMillis())後傳送給pcService,pcService將2個渠道的內容比較,相同時,把對應手機號碼返回給clients。

(這個流程中,很多不靠譜的情況大家可想而知了,不止是客戶端,伺服器也要做簡訊超時和請求超時判斷,還有要用個專門的手機一直執行著)

我觀察了很多類似軟體,都是先嚐試去獲取手機號,取不到就提示使用者手動輸入,或者提示使用者發簡訊一鍵註冊。。沒有非得一次性成功的。。再說了,偷偷發簡訊很多電子市場是會掃原始碼的,這樣的話軟體就沒法上線了