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卡也沒有儲存手機號)

[java] view plaincopy
  1. String telephoneNumber = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE).getLine1Number();  
[html] view plaincopy
  1. <uses-permission android:name="android.permission.READ_PHONE_STATE" />  


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

[html] view plaincopy
  1. <receiver android:name=".broadcast.PhoneStatReceiver">  
  2.    <intent-filter>  
  3.     <action android:name="android.intent.action.PHONE_STATE" />  
  4.     <action android:name="android.intent.action.NEW_OUTGOING_CALL" />  
  5.    </intent-filter>  
  6.   </receiver>  


加幾個權限

[html] view plaincopy
  1. <uses-permission android:name="android.permission.CALL_PHONE" />  
  2. <uses-permission android:name="android.permission.CALL_PRIVILEGED" />  
  3. <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
  4. lt;uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />  


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

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


 如果項目中非要用到用戶的真實手機號,有一個很麻煩的辦法可以做到:

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

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

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章