Android本机号码手机与提交方案

最近一轮迭代改成了用验证码的方式去获取手机号,所以这个方案也没有意义了,权当作记录吧。


Android本机号码手机与提交方案

一、背景:

1、能直接获取号码:

TelephonyManager tm = (TelephonyManager)this. getSystemService( Context.TELEPHONY_SERVICE);

String deviceid = tm.getDeviceId();

String tel = tm.getLine1Number();//手机号码

String imei = tm.getSimSerialNumber();

String imsi = tm.getSubscriberId();

能直接获取到tel,这件事情就算完了。

2、得向运营商查询:

简单说就是:国内运营商们采用了一种先进的技术,把电话号码和SIM卡分离,部分新手机卡,电话号码不能从SIM获得。(SIM卡唯一的识别标志是IMSI码。)

3WAP获取手机号http://wap.10086.cn/ywcx/zdcx.jsp

以移动为例,CMWAP用的是移动的内网,手机请求通过网关时,网关对请求的head部分注入当前手机号。注入的这个手机号只有被授权的SP服务商之类的才能看到。

很多网站宣传能有40~60%的概率获取手机号就是用WAP的用户比例大概为40~60%,一般在网站后台做识别处理输出。

 

二、完整的方案可能是:

 

ü 获取手机号:

A、短信、电话查询运营商,截获短信。读取短信,获取短信记录中,当前时间戳内可信的电话号码。把号码和IMSI存进SharedPreferences或者文件中。

B、查看用户是不是使用流量,是不是使用WAP,切换到WAP,关闭wifi,模拟打开10086 wap网站,获取上面显示的号码,把号码和IMSI存进缓存中,切换回原来的通讯方式

C、用手机发短信,短信内容是当前号码的IMSI到短信机,每次登陆、退出登陆都用IMSI和后台通讯

ü 获取已存储的手机号:

1、查询SIM有没有手机号码?

2、查询是否有缓存电话号码记录?

ü 更新手机号:

1、登陆时向后台更新电话号码

2、退出登陆时清除电话号码

 

三、具体实现

用第一种方式处理。一次获取本机号码的过程如下:

1、检测是否有SIM卡(有IMSI号码)

TelephonyManager iTelephonyMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

String IMSI = iTelephonyMgr.getSubscriberId();

if(IMSI == null || IMSI.length() == 0){return false;}

2、检测是都有缓存:

String key = getIMSIKey(context);

return CAppDataModel.GetStaticString(key,"");

 

private String getIMSIKey(Context context){

TelephonyManager mTelephonyMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

String imsi =  mTelephonyMgr.getSubscriberId();

if(imsi != null && imsi.length() != 0){

return ConstVal.CGlobalKey.SIM_IMSI_PREFIX + imsi;

}

return "";

}

3、 判断运营商:

private boolean MarkSimOperator(){

String operator = iTelephonyMgr.getSimOperator();

if(operator != null){

if(operator.equals("46000") || operator.equals("46002")|| operator.equals("46007")){

SimOperator = 0x0001;//移动

}else if(operator.equals("46001")){

SimOperator = 0x0002;//联通

}else if(operator.equals("46003")){

SimOperator = 0x0004;//电信

}

}

return SimOperator != 0;//is mark success

}

4、获取SIM卡上固化的电话号码:

String Phone = iTelephonyMgr.getLine1Number();

5、获取不到发短信:

SmsManager manage=SmsManager.getDefault();

PendingIntent sentIntent = PendingIntent.getBroadcast(refer, 0,new Intent(), 0);

manage.sendTextMessage(getAddress(), null, getMessage(), sentIntent,null);

6、定期检查短信(6s查一次,查60次)

 

 

 

private String readSmsDataBaseToGetPhone(Context context){

String address = getAddress();

    Sms objSms = new Sms();

    Uri message = Uri.parse("content://sms/inbox");

    Cursor c = context.getContentResolver().query(message, null,null,null,"date DESC");

    int totalSMS = c.getCount();

    if (c.moveToFirst()) {

        for (int i = 0; i < totalSMS; i++) {

            objSms = new Sms();

            objSms.setAddress(c.getString(c.getColumnIndexOrThrow("address")));

            objSms.setMsg(c.getString(c.getColumnIndexOrThrow("body")));

            objSms.setReadState(c.getString(c.getColumnIndex("read")));

            objSms.setTime(c.getString(c.getColumnIndexOrThrow("date")));

            

            if(c.getString(c.getColumnIndexOrThrow("date")).compareTo(StackTop) <= 0){

             c.close();

             return "";

            }

            if(objSms.is(address)){

             String str = objSms.getPhoneFromMessage(getMessageMacher());

             if(Number.isNumeric(str)){

             c.close();

             return str;

             }

            }

            c.moveToNext();

        }

    }

    c.close();

    return "";

}

备注1:StackTop是我获取的时间戳,即发短信前,短信数据库最近一次收到短信的时间。数据库输出按时间排序

备注2EnsurePhoneNumExited()函数会 重复1~6的步骤

 

7,监听短信的到来,读取获取到的短信
代码(略) 

上述过程中有一个步骤获取到号码,或者是检查到无SIM卡,或者是SIM卡中有号码即退出

 

流程图如下:(略)

 

四、解释问题:

要解释清楚几个容易出错的问题处理:

1.每个运营商都有2个指令,什么情况下会切换使用

不幸的是,目前只有联通找到两个指令,每次发完信息后,我会记住发信息的次数,按当前发信息的次数是奇书、偶数来切换指令,具体代码如下:

 

2.短信内容解析提取号码的方法是什么?

关键字匹配 + 号码长度匹配

Macher = new String[]{"流量","剩余"};

public String getPhoneFromMessage(String[] macher){

if(macher == null || _msg ==null || _msg.length() == 0){return NULL;}

for(String ms:macher){// 关键字匹配

if(!_msg.contains(ms)){return NULL; }

}

String[] nums = _msg.split("\\D+");

for(String s:nums){ //号码长度要求

if(s.length() >= MinPhoneLength){

return s;

}

}

return NULL;

}

关键字:我们发信息查指令,运营商返回的信息必然会包括一些特殊关键字。但在等待回执过程中,可能运营商会回复一些垃圾短信、多个号码的短信,必须过滤掉这些东西。

 

3.什么时候需要发送短信获取号码

   “有SIM&&获取不到用IMSI码作为键值的缓存号码&& SIM卡中没有固化手机号码”

4.怎么判断双卡双待:

  这个问题是我想多了。原生Android的设计只有单卡,双卡是国内的杰作。所以国内区分了主卡和次卡的概念。用android api获取到的是主卡,次卡得用反射才能拿到。只有一张卡时,那张卡被系统默认为主卡,现在的处理是不管有没有次卡,直接用主卡去匹配。

 

 5.兼容性问题:

  有些手机,例如 小米,明明有信息过来,就是读不到短信内容,是因为第三方rom修改了sms的contentProvider,只允许应用读那些非验证码的信息,遇到这种情况,获取手机号码就失败了。

 

五,小结
因为一些因素,单纯从技术的维度,很难稳定的获取到手机号码。
方案能实施下去是因为:
1,我们的实施人员在场,广东地区
2,用户用小辣椒、酷派这种接近原生android机

后来客户在不同区域,然后用户机型也开始多样化,频繁收到短信用户觉得很骚扰,不发信息验证又拿不到手机号。
最后我们还是用了手机验证码的方案。所以这个方案就被弃了。 
 

 

 

 

 

 

 

 

 

 

Yeshen in Landowsoft

2015.11.24


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值