国际手机号码有效性校验

手机号码已经几乎成为用户注册的必填信息,所以在没有验证码校验的场景下,对其进行格式的校验显得尤为重要。

一、闲谈

    手机号码的格式千变万化,不同国家的手机号码格式有很大的差异,细细研究,会发现很多有意思的事情,

    比如:

        你以为手机号码都是数字组成的?当然不,

            在以色列,1-800-Flowers 也是一个合法的手机号,

            而在埃及,手机号码可能是下面的象形文字哦

                libphonenumber01.png

    其实这些有趣的小故事都可以在 google 开源的库中找到:地址

    所以,很显然,本文所提及的解决方案,其实就是 google 的这个类库的使用方法。


</p>

二、设计

    关于手机号校验的设计,会涉及到几个点:

    ① 手机号码数据类型

        上文也提过,手机号码也会出现字符哦,所以,肯定不能使用 int 等数字类型,况且手机号码也基本不会用来进行计算操作。

    ② 长度

        手机号码长度其实是依据各个国家的设计而不相同的,

        比如大陆就是11位手机号,而瑞士,据说会有8位的号码。

        那么应该使用多长的字段来保存呢?其实手机号保留 20 位长度,目前是比较安全的,所以,数据库设计为 varchar 50 是妥妥没问题的。

    ③ 页面设计

        其实最佳的体验是分为两个框,一个下拉框用来选择区号,另一个输入框用来输入手机号。

    ④ 手机号校验

        诚然,如果强制要求有验证码校验,那么是最佳的,但时如果没有的话,那么在此推荐 google 的手机号码校验类库:libphonenumber

        比如亚马逊aws的注册页面,就没有进行号码的规制校验,但时强制使用了验证码校验。

        关于 libphonenumber,该类库提供了 Java、JS等实现,上手简单,功能强大。而且还提供了运营商查询、归属地查询等功能。


三、类库的使用

    ① jar包引入

        如果是使用 maven 来构建地址,需要引入如下几个库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
&nbsp;&nbsp;&nbsp;&nbsp;<!--手机号解析-->&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;<dependency>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<groupId>com.googlecode.libphonenumber</groupId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<artifactId>libphonenumber</artifactId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<version>8.9.9</version>
&nbsp;&nbsp;&nbsp;&nbsp;</dependency>
&nbsp;&nbsp;&nbsp;&nbsp;<!--手机归属地定位相关-->
&nbsp;&nbsp;&nbsp;&nbsp;<dependency>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<groupId>com.googlecode.libphonenumber</groupId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<artifactId>geocoder</artifactId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<version>2.99</version>
&nbsp;&nbsp;&nbsp;&nbsp;</dependency>
&nbsp;&nbsp;&nbsp;&nbsp;<!--&nbsp;手机运营商相关&nbsp;-->
&nbsp;&nbsp;&nbsp;&nbsp;<dependency>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<groupId>com.googlecode.libphonenumber</groupId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<artifactId>carrier</artifactId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<version>1.9</version>
&nbsp;&nbsp;&nbsp;&nbsp;</dependency>
&nbsp;&nbsp;&nbsp;&nbsp;<dependency>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<groupId>com.googlecode.libphonenumber</groupId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<artifactId>prefixmapper</artifactId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<version>2.99</version>
&nbsp;&nbsp;&nbsp;&nbsp;</dependency>

    ② 工具类代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;com.google.i18n.phonenumbers.NumberParseException;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;com.google.i18n.phonenumbers.PhoneNumberToCarrierMapper;
&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;com.google.i18n.phonenumbers.PhoneNumberUtil;
&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;com.google.i18n.phonenumbers.Phonenumber;
&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;java.util.HashMap;
&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;java.util.Locale;
&nbsp;&nbsp;&nbsp;&nbsp;import&nbsp;java.util.Map;
&nbsp;&nbsp;&nbsp;&nbsp;/**
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Author:&nbsp;Jet
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Description:&nbsp;国际手机号校验
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Date:&nbsp;2018/5/9&nbsp;9:20
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;class&nbsp;LibphonenumberUtil&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;PhoneNumberUtil&nbsp;phoneNumberUtil&nbsp;=&nbsp;PhoneNumberUtil.getInstance();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;PhoneNumberToCarrierMapper&nbsp;carrier&nbsp;=&nbsp;PhoneNumberToCarrierMapper.getInstance();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;PhoneNumberOfflineGeocoder&nbsp;geocoder&nbsp;=&nbsp;PhoneNumberOfflineGeocoder.getInstance();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;String&nbsp;DEFAULT_COUNTRY&nbsp;=&nbsp;"CN";
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;static&nbsp;final&nbsp;String[]&nbsp;phoneCases&nbsp;=&nbsp;new&nbsp;String[]&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"8618611234515",&nbsp;&nbsp;//中国&nbsp;true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"00886912347718",&nbsp;&nbsp;&nbsp;//台湾
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"006581234994",&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//新加坡
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"15911234718",&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//中国
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"008201234704546",&nbsp;&nbsp;//Korea
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"17091234155"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//中国170
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;final&nbsp;Map<String,&nbsp;String>&nbsp;CHINESE_CARRIER_MAPPER&nbsp;=&nbsp;new&nbsp;HashMap<>();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;static&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CHINESE_CARRIER_MAPPER.put("China&nbsp;Mobile",&nbsp;"中国移动");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CHINESE_CARRIER_MAPPER.put("China&nbsp;Unicom",&nbsp;"中国联通");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CHINESE_CARRIER_MAPPER.put("China&nbsp;Telecom",&nbsp;"中国电信");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(doGeo("17811981865",&nbsp;"86"));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Author:&nbsp;Jet
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Description&nbsp;①&nbsp;可以加区号,也可以不加,区号默认86
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;②&nbsp;区号前面的“+”和“00”占位可加可不加
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;②&nbsp;手机号中间可以增加“-”
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;phone&nbsp;“+8617717031234&nbsp;+008617717031234&nbsp;8617717031234&nbsp;177-1703-1234”
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Date:&nbsp;2018/5/9&nbsp;9:21
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;boolean&nbsp;doValidUniversal(String&nbsp;phone)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Phonenumber.PhoneNumber&nbsp;phoneNumber&nbsp;=&nbsp;doParse(phone);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;phoneNumber.hasNationalNumber()&nbsp;&&&nbsp;doValid(phoneNumber.getNationalNumber()&nbsp;+&nbsp;"",&nbsp;phoneNumber.getCountryCode()&nbsp;+&nbsp;"");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Author:&nbsp;Jet
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Description&nbsp;电话解析逻辑
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;phone&nbsp;“+8617717031234&nbsp;+008617717031234&nbsp;8617717031234&nbsp;177-1703-1234””
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;电话实体类&nbsp;Phonenumber.PhoneNumber
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Date:&nbsp;2018/5/9&nbsp;9:21
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;Phonenumber.PhoneNumber&nbsp;doParse(String&nbsp;phone)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;phoneNumberUtil.parse(phone,&nbsp;DEFAULT_COUNTRY);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;catch&nbsp;(NumberParseException&nbsp;e)&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;NumberFormatException("invalid&nbsp;phone&nbsp;number:&nbsp;"&nbsp;+&nbsp;phone);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Author:&nbsp;Jet
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Description&nbsp;手机校验逻辑
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;phoneNumber&nbsp;手机号
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;countryCode&nbsp;手机区号
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Date:&nbsp;2018/5/9&nbsp;9:21
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;boolean&nbsp;doValid(String&nbsp;phoneNumber,&nbsp;String&nbsp;countryCode){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;ccode&nbsp;=&nbsp;Integer.parseInt(countryCode);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long&nbsp;phone&nbsp;=&nbsp;Long.parseLong(phoneNumber);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Phonenumber.PhoneNumber&nbsp;pn&nbsp;=&nbsp;new&nbsp;Phonenumber.PhoneNumber();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pn.setCountryCode(ccode);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pn.setNationalNumber(phone);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;phoneNumberUtil.isValidNumber(pn);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Author:&nbsp;Jet
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Description&nbsp;手机运营商
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;phoneNumber&nbsp;手机号
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;countryCode&nbsp;手机区号
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;能转成中文则返回中文,否则返回英文的
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Date:&nbsp;2018/5/9&nbsp;9:21
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;String&nbsp;doCarrier(String&nbsp;phoneNumber,&nbsp;String&nbsp;countryCode){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;ccode&nbsp;=&nbsp;Integer.parseInt(countryCode);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long&nbsp;phone&nbsp;=&nbsp;Long.parseLong(phoneNumber);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Phonenumber.PhoneNumber&nbsp;pn&nbsp;=&nbsp;new&nbsp;Phonenumber.PhoneNumber();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pn.setCountryCode(ccode);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pn.setNationalNumber(phone);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//返回结果只有英文,自己转成成中文
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;carrierEn&nbsp;=&nbsp;carrier.getNameForNumber(pn,&nbsp;Locale.ENGLISH);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;CHINESE_CARRIER_MAPPER.containsKey(carrierEn)?CHINESE_CARRIER_MAPPER.get(carrierEn):carrierEn;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/**
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Author:&nbsp;Jet
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Description&nbsp;手机归属地
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;phoneNumber&nbsp;手机号
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;countryCode&nbsp;手机区号
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@Date:&nbsp;2018/5/9&nbsp;9:21
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;String&nbsp;doGeo(String&nbsp;phoneNumber,&nbsp;String&nbsp;countryCode){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;ccode&nbsp;=&nbsp;Integer.parseInt(countryCode);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;long&nbsp;phone&nbsp;=&nbsp;Long.parseLong(phoneNumber);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Phonenumber.PhoneNumber&nbsp;pn&nbsp;=&nbsp;new&nbsp;Phonenumber.PhoneNumber();
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pn.setCountryCode(ccode);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pn.setNationalNumber(phone);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;geocoder.getDescriptionForNumber(pn,&nbsp;Locale.CHINESE);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}

        ③ 工具类使用说明

            结构很简单,见下图:

            libphonenumber02.png





四、总结

    ① 由于手机号码的规则一直是处于更新状态的,所以建议jar包的版本要常更新,

        可以常逛逛 maven 仓库:https://repo1.maven.org/maven2/com/googlecode/libphonenumber/

    ② 手机号校验千万要加区号,否则会有歧义,如下 10 位长度手机号:

        857 498 4492

        10位手机号按理应该是国外的,但是你如果使用国内的区号来校验会发现,该号码是“贵州毕节”的,

        至于该号码到底是什么,暂未摸清楚。






------ 本文结束 感谢阅读 ------
0%