来源:http://www.cnblogs.com/android100/p/android-get-num.html
最近做到一个项目,需要获取手机号。项目中使用的手机卡为电信卡,那么就以此为例吧。
网上不符合需求的方法
Google了一下,网上的做法如下:
- //获取手机号码
- TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
- String deviceid = tm.getDeviceId();//获取智能设备唯一编号
- String te1 = tm.getLine1Number();//获取本机号码
- String imei = tm.getSimSerialNumber();//获得SIM卡的序号
- String imsi = tm.getSubscriberId();//得到用户Id
添加权限:
- <uses-permissionandroid:nameuses-permissionandroid:name="android.permission.READ_PHONE_STATE"/
以上做法有可能获取sim卡号,但是现在最起码在电信手机卡上获取不到。
原因好像、似乎是:
手机号码不是所有的都能获取。只是有一部分可以拿到。这个是由于移动运营商没有把手机号码的数据写入到sim卡中.SIM卡只有唯一的编号,供网络与设备识别那就是IMSI号码,手机的信号也可以说是通过这个号码在网络中传递的,并不是手机号码。试想,你的SIM卡丢失后,补办一张新的会换号码吗?是不会的.就是因为在你的手机号码对应的IMSI号 在移动运营商中被修改成新SIM卡的IMSI号码。
那么我们怎么解决这个问题呢?
不好实现?一个原因搞定你:项目需要!!
查了下手机的基本信息那一栏里,也没有找到手机号,看来手机中似乎没有存储这手机号。那么我就只有使用变通的手法来获取手机号了。
就是给10001发送一个短信,找了一下,发个501查询套餐情况就可以。10001会给你个反馈信息,其中包含手机号码
那么我们发送短信,然后监听得到此短信,然后分解字符串那么就可以得到手机号了。
如果是联通或者移动应该也是有类似的情况。何况给他们发短信应该不会收费。。。O(∩_∩)O~
程序如何实现?
1.监听短信类
- package com.example.smsmanager;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.telephony.SmsMessage;
- public class SMS_Receiver extends BroadcastReceiver {
- final String GetNumberAddress="10001";
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
- Object[] pdus=(Object[])intent.getExtras().get("pdus");
- //不知道为什么明明只有一条消息,传过来的却是数组,也许是为了处理同时同分同秒同毫秒收到多条短信
- //但这个概率有点小
- SmsMessage[] message=new SmsMessage[pdus.length];
- StringBuilder sb=new StringBuilder();
- System.out.println("pdus长度"+pdus.length);
- String address="";
- for(int i=0;i<pdus.length;i++){
- //虽然是循环,其实pdus长度一般都是1
- message[i]=SmsMessage.createFromPdu((byte[])pdus[i]);
- sb.append("接收到短信来自:\n");
- address=message[i].getDisplayOriginatingAddress();
- sb.append(address+"\n");
- sb.append("内容:"+message[i].getDisplayMessageBody());
- }
- System.out.println(sb.toString());
- if(SMSCore.PhoneNumber==""&&address.equals(GetNumberAddress)){
- SMSCore.PhoneNumber=SMSCore.GetPhoneNumberFromSMSText(sb.toString());
- MessageTools.ShowDialog(context, address);
- }
- MessageTools.ShowDialog(context, sb.toString().trim());
- MessageTools.ShowDialog(context, SMSCore.PhoneNumber);
- }
- }
- }
- package com.example.smsmanager;
- import java.sql.Date;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.content.BroadcastReceiver;
- import android.app.Activity;
- import android.app.PendingIntent;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.telephony.SmsManager;
- import android.util.Log;
- import android.content.ContextWrapper;
- public class SMSCore {
- public static String PhoneNumber="";
- //==============Get Phone Number ==============================
- //get the phone number from sms
- public static String GetPhoneNumberFromSMSText(String sms){
- List<String> list=GetNumberInString(sms);
- for(String str:list){
- if(str.length()==11)
- return str;
- }
- return "";
- }
- public static List<String> GetNumberInString(String str){
- List<String> list=new ArrayList<String>();
- String regex = "\\d*";
- Pattern p = Pattern.compile(regex);
- Matcher m = p.matcher(str);
- while (m.find()) {
- if (!"".equals(m.group()))
- list.add(m.group());
- }
- return list;
- }
- //===========================================================
- //
- //
- //=============Send SMS================
- public void SendSMS(String number,String text,Context context){
- PendingIntent pi = PendingIntent.getActivity(context, 0,
- new Intent(context, context.getClass()), 0);
- SmsManager sms = SmsManager.getDefault();
- sms.sendTextMessage(number, null, text, pi, null);
- }
- public void SendSMS2(String number,String text,Context context){
- String SENT = "sms_sent";
- String DELIVERED = "sms_delivered";
- PendingIntent sentPI = PendingIntent.getActivity(context, 0, new Intent(SENT), 0);
- PendingIntent deliveredPI = PendingIntent.getActivity(context, 0, new Intent(DELIVERED), 0);
- //
- // //
- // registerReceiver(new BroadcastReceiver(){
- // @Override
- // public void onReceive(Context context, Intent intent){
- // switch(getResultCode())
- // {
- // case Activity.RESULT_OK:
- // Log.i("====>", "RESULT_OK");
- // System.out.println("RESULT_OK");
- //
- // break;
- // case Activity.RESULT_CANCELED:
- // Log.i("=====>", "RESULT_CANCELED");
- // break;
- // }
- // }
- // }, new IntentFilter(DELIVERED));
- // //
- SmsManager smsm = SmsManager.getDefault();
- smsm.sendTextMessage(number, null, text, sentPI, deliveredPI);
- }
- //=====================================
- }
3.弹出框操作类
- package com.example.smsmanager;
- import android.app.AlertDialog;
- import android.app.AlertDialog.Builder;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.DialogInterface.OnClickListener;
- public class MessageTools {
- public static void ShowDialog(Context context, String text){
- AlertDialog.Builder builder = new Builder(context);
- builder.setMessage(text);
- builder.setTitle("提示");
- builder.setPositiveButton("确认", new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- dialog.dismiss();
- }
- });
- builder.setNegativeButton("取消", new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.dismiss();
- }
- });
- builder.create().show();
- }
- }
4.调用如下:
- //
- private static final String ACTION_SMS_SEND = "lab.sodino.sms.send";
- private static final String ACTION_SMS_DELIVERY = "lab.sodino.sms.delivery";
- private static final String ACTION_SMS_RECEIVER = "android.provider.Telephony.SMS_RECEIVED";
- // 注册接收下行receiver
- SMS_Receiver smsReceiver= new SMS_Receiver();
- IntentFilter receiverFilter = new IntentFilter(ACTION_SMS_RECEIVER);
- registerReceiver(smsReceiver, receiverFilter);
- //发送短信
- SMSCore smscore=new SMSCore();
- smscore.SendSMS2("10001", "501", context);
运行结果:
我们可以得到了想要的手机号码了!
------------------------------------------------------------------------------------------------------------------------------------------------
下面我从开发的角度,简单写一下如何获取手机设备信息和手机号码
准备条件:一部安卓手机、手机SIM卡确保插入手机里、eclipse ADT和-sdk开发环境
第一步:新建一个android工程(JinshanTest),
并需要在工程的AndroidManifest.xml文件中,添加权限
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
图例:
第二步:新建一个工具类PhoneInfo.
- package com.jinshan.test;
- import android.content.Context;
- import android.telephony.TelephonyManager;
- /**
- * 读取手机设备信息测试代码
- * http://www.souapp.com 搜应用网
- * song2c@163.com
- * 宋立波
- */
- public class PhoneInfo {
- private TelephonyManager telephonyManager;
- /**
- * 国际移动用户识别码
- */
- private String IMSI;
- private Context cxt;
- public PhoneInfo(Context context) {
- cxt=context;
- telephonyManager = (TelephonyManager) context
- .getSystemService(Context.TELEPHONY_SERVICE);
- }
- /**
- * 获取电话号码
- */
- public String getNativePhoneNumber() {
- String NativePhoneNumber=null;
- NativePhoneNumber=telephonyManager.getLine1Number();
- return NativePhoneNumber;
- }
- /**
- * 获取手机服务商信息
- */
- public String getProvidersName() {
- String ProvidersName = "N/A";
- try{
- IMSI = telephonyManager.getSubscriberId();
- // IMSI号前面3位460是国家,紧接着后面2位00 02是中国移动,01是中国联通,03是中国电信。
- System.out.println(IMSI);
- if (IMSI.startsWith("46000") || IMSI.startsWith("46002")) {
- ProvidersName = "中国移动";
- } else if (IMSI.startsWith("46001")) {
- ProvidersName = "中国联通";
- } else if (IMSI.startsWith("46003")) {
- ProvidersName = "中国电信";
- }
- }catch(Exception e){
- e.printStackTrace();
- }
- return ProvidersName;
- }
- public String getPhoneInfo(){
- TelephonyManager tm = (TelephonyManager)cxt.getSystemService(Context.TELEPHONY_SERVICE);
- StringBuilder sb = new StringBuilder();
- sb.append("\nDeviceId(IMEI) = " + tm.getDeviceId());
- sb.append("\nDeviceSoftwareVersion = " + tm.getDeviceSoftwareVersion());
- sb.append("\nLine1Number = " + tm.getLine1Number());
- sb.append("\nNetworkCountryIso = " + tm.getNetworkCountryIso());
- sb.append("\nNetworkOperator = " + tm.getNetworkOperator());
- sb.append("\nNetworkOperatorName = " + tm.getNetworkOperatorName());
- sb.append("\nNetworkType = " + tm.getNetworkType());
- sb.append("\nPhoneType = " + tm.getPhoneType());
- sb.append("\nSimCountryIso = " + tm.getSimCountryIso());
- sb.append("\nSimOperator = " + tm.getSimOperator());
- sb.append("\nSimOperatorName = " + tm.getSimOperatorName());
- sb.append("\nSimSerialNumber = " + tm.getSimSerialNumber());
- sb.append("\nSimState = " + tm.getSimState());
- sb.append("\nSubscriberId(IMSI) = " + tm.getSubscriberId());
- sb.append("\nVoiceMailNumber = " + tm.getVoiceMailNumber());
- return sb.toString();
- }
- }
第三步:在启动的Activity,JinshanTestActivity中添加,调用代码:
- package com.jinshan.test;
- import android.app.Activity;
- import android.os.Bundle;
- public class JinshanTestActivity extends Activity {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- PhoneInfo siminfo = new PhoneInfo(JinshanTestActivity.this);
- System.out.println("getProvidersName:"+siminfo.getProvidersName());
- System.out.println("getNativePhoneNumber:"+siminfo.getNativePhoneNumber());
- System.out.println("------------------------");
- System.out.println("getPhoneInfo:"+siminfo.getPhoneInfo());
- }
- }
第四步,把手机使用USB线,连接到电脑上,确保是连通性,开始运行工程
最后,我们看LOGCAT日志,结果如下:
------------------------------------------------------------
04-01 16:20:57.105: I/System.out(952): 460003121934674
04-01 16:20:57.105: I/System.out(952): getProvidersName:中国移动04-01 16:20:57.115: I/System.out(952): getNativePhoneNumber:136XXXXXXX04-01 16:20:57.115: I/System.out(952): ------------------------04-01 16:20:57.145: I/System.out(952): getPhoneInfo:04-01 16:20:57.145: I/System.out(952): DeviceId(IMEI) = 352XXXXXXXX6132804-01 16:20:57.145: I/System.out(952): DeviceSoftwareVersion = 0104-01 16:20:57.145: I/System.out(952): Line1Number = 136XXXXXXX04-01 16:20:57.145: I/System.out(952): NetworkCountryIso = cn04-01 16:20:57.145: I/System.out(952): NetworkOperator = 4600004-01 16:20:57.145: I/System.out(952): NetworkOperatorName = 中国移动04-01 16:20:57.145: I/System.out(952): NetworkType = 204-01 16:20:57.145: I/System.out(952): PhoneType = 104-01 16:20:57.145: I/System.out(952): SimCountryIso = cn04-01 16:20:57.145: I/System.out(952): SimOperator = 4600004-01 16:20:57.145: I/System.out(952): SimOperatorName = CMCC04-01 16:20:57.145: I/System.out(952): SimSerialNumber = 898xxxxxx9010804-01 16:20:57.145: I/System.out(952): SimState = 504-01 16:20:57.145: I/System.out(952): SubscriberId(IMSI) = 46000xxxxxxxx4674那么我们来解释一下上面的信息具体代表啥意思。
getNativePhoneNumber 获取的手机号
DeviceId(IMEI)手机 国际移动用户识别码
NetworkOperator 移动运营商编号
NetworkOperatorName 移动运营商名称
SimSerialNumber SimOperator SimCountryIso SimSerialNumber SubscriberId(IMSI) 关于手机SIM卡的一些详细信息
其实代码中没有写 获取System.ANDROID_ID这个操作,因为很多手机设备获取不到andnroid_id
当然了,我们今天主要讲述<uses-permission android:name="android.permission.READ_PHONE_STATE"/> 光使用这个权限我们可以获得的手机设备信息和手机号
如果想获得WIFI,蓝牙,GPS,读写SDCARD更多的信息,就需要添加其它的权限。
此外,本次我拿自己的手机SIM卡测试是可以获取到手机号码的,当然了有些手机号码是获取不到的,这里也给大家罗列了原因,
手机号码不是所有的都能获取。只是有一部分可以拿到。
这个是由于移动运营商没有把手机号码的数据写入到sim卡中.SIM卡只有唯一的编号,供网络与设备识别那就是IMSI号码,手机的信号也可以说是通过这个号码在网络中传递的,并不是手机号码。试想,你的SIM丢失后,补办一张新的会换号码吗?是不会的.就是因为在你的手机号码对应的IMSI号 在移动运营商中被修改成新SIM卡的IMSI号码。
那么手机号为什么有的就能显示呢? 这个就像是一个变量,当移动运营商为它赋值了,它自然就会有值。不赋值自然为空。 对于移动的用户,手机号码(MDN)保存在运营商的服务器中,而不是保存在SIM卡里。SIM卡只保留了IMSI和一些验证信息。手机每次入网注册的时候,都会以短信的形式将IMSI及验证信息上传到运营商的服务器,服务器在完成注册动作之后,会以短信的形式将注册的结果下发到手机里。下发的内容会因条件不同而不同。 如果服务器在下发的短信中,不包含手机的号码,手机是无法取得电话号码。如果短信中包含了号码,手机才会将其缓存,以备他用.此外,对于其他运行商的SIM卡或者UIM卡,MDN有可能保存在UIM卡中。100%能够取得本机号码不太可能。 移动神州行,联通的卡是可以取到的.动感地带的取不到.别的卡还没有试过. 能够读取SIM卡号的话应该有前提.那就是SIM卡已经写入了本机号码,不然是无法读取的。