最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

android autolink识别错误,TextView autoLink=phone 在8.1机器上无效

互联网 admin 19浏览 0评论

android autolink识别错误,TextView autoLink=phone 在8.1机器上无效

前言

某天,QA给我提了一个Bug,说是包裹物流追踪的电话不能自动识别了。正常情况如下图所示:

物流追踪

在8.1的机器上,TextView突然不能自动识别电话号码了。

1.电话号码识别

Android SDK中,TextView提供了一个autoLink属性来帮助我们识别各种各样的链接,我们只需要将autoLink属性设置为"phone",就能轻易识别出电话号码。

这个属性在8.1之前的机器上是可以正常工作的,然而在8.1的机器上突然不可以了。那么原因是为何呢?

2.原因探究

通过查看TextView的源码,我们可以知道,系统是借助了一个名叫Linkify的类来识别电话号码的,具体可以查看文章——autoLink实现原理

第一个回答中解释了为何autoLink会无效,我们可以了解到,autoLink跟手机的语言有关(英文或中文)。

首先看下Linkify的关键代码在8.1之前的实现:

private static final void gatherTelLinks(ArrayList links, Spannable s) {

PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();

Iterable matches = phoneUtil.findNumbers(s.toString(),

Locale.getDefault().getCountry(), Leniency.POSSIBLE, Long.MAX_VALUE);

for (PhoneNumberMatch match : matches) {

LinkSpec spec = new LinkSpec();

spec.url = "tel:" + PhoneNumberUtils.normalizeNumber(match.rawString());

spec.start = match.start();

spec.end = match.end();

links.add(spec);

}

}

从上面代码我们可以看到,phoneUtil.findNumbers函数中传入了Locale.getDefault().getCountry(),即国家码,所以如果当前手机的地区变动,那么可能某些电话号码就不会被正确识别了。

然后再看下8.1上Linkify代码的实现:

private static void gatherTelLinks(ArrayList links, Spannable s,

@Nullable Context context) {

PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();

final TelephonyManager tm = (context == null)

? TelephonyManager.getDefault()

: TelephonyManager.from(context);

Iterable matches = phoneUtil.findNumbers(s.toString(),

tm.getSimCountryIso().toUpperCase(Locale.US),

Leniency.POSSIBLE, Long.MAX_VALUE);

for (PhoneNumberMatch match : matches) {

LinkSpec spec = new LinkSpec();

spec.url = "tel:" + PhoneNumberUtils.normalizeNumber(match.rawString());

spec.start = match.start();

spec.end = match.end();

links.add(spec);

}

}

以上代码可以看到,原本传入地区码的地方,变成了getSimCountryIso()。那么看下这个函数的注解:

/**

* Returns the ISO country code equivalent of the current registered

* operator's MCC (Mobile Country Code).

*

* Availability: Only when user is registered to a network. Result may be

* unreliable on CDMA networks (use {@link #getPhoneType()} to determine if

* on a CDMA network).

*/

public String getNetworkCountryIso() {

return getNetworkCountryIsoForPhone(getDefaultPhone());

}

翻译过来就是获取当前运营商注册的国家码。而QA的测试机是没有插入sim卡的,那么这个函数返回的CountryCode绝对不是CN(具体返回啥由底层ROM决定)

在测试机插入sim卡之后,TextView的autolink又正确工作了,所以可以确定问题是出在这里。

3.总结

8.1之前的手机,TextView的电话号码匹配和当前手机的地区有关,切换语言时有可能导致号码匹配失效。

大于等于8.1的手机上,号码匹配和当前手机插入的sim卡有关,当使用国外的SIM卡或者不插入SIM卡时,有可能会导致号码匹配失效。

android autolink识别错误,TextView autoLink=phone 在8.1机器上无效

前言

某天,QA给我提了一个Bug,说是包裹物流追踪的电话不能自动识别了。正常情况如下图所示:

物流追踪

在8.1的机器上,TextView突然不能自动识别电话号码了。

1.电话号码识别

Android SDK中,TextView提供了一个autoLink属性来帮助我们识别各种各样的链接,我们只需要将autoLink属性设置为"phone",就能轻易识别出电话号码。

这个属性在8.1之前的机器上是可以正常工作的,然而在8.1的机器上突然不可以了。那么原因是为何呢?

2.原因探究

通过查看TextView的源码,我们可以知道,系统是借助了一个名叫Linkify的类来识别电话号码的,具体可以查看文章——autoLink实现原理

第一个回答中解释了为何autoLink会无效,我们可以了解到,autoLink跟手机的语言有关(英文或中文)。

首先看下Linkify的关键代码在8.1之前的实现:

private static final void gatherTelLinks(ArrayList links, Spannable s) {

PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();

Iterable matches = phoneUtil.findNumbers(s.toString(),

Locale.getDefault().getCountry(), Leniency.POSSIBLE, Long.MAX_VALUE);

for (PhoneNumberMatch match : matches) {

LinkSpec spec = new LinkSpec();

spec.url = "tel:" + PhoneNumberUtils.normalizeNumber(match.rawString());

spec.start = match.start();

spec.end = match.end();

links.add(spec);

}

}

从上面代码我们可以看到,phoneUtil.findNumbers函数中传入了Locale.getDefault().getCountry(),即国家码,所以如果当前手机的地区变动,那么可能某些电话号码就不会被正确识别了。

然后再看下8.1上Linkify代码的实现:

private static void gatherTelLinks(ArrayList links, Spannable s,

@Nullable Context context) {

PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();

final TelephonyManager tm = (context == null)

? TelephonyManager.getDefault()

: TelephonyManager.from(context);

Iterable matches = phoneUtil.findNumbers(s.toString(),

tm.getSimCountryIso().toUpperCase(Locale.US),

Leniency.POSSIBLE, Long.MAX_VALUE);

for (PhoneNumberMatch match : matches) {

LinkSpec spec = new LinkSpec();

spec.url = "tel:" + PhoneNumberUtils.normalizeNumber(match.rawString());

spec.start = match.start();

spec.end = match.end();

links.add(spec);

}

}

以上代码可以看到,原本传入地区码的地方,变成了getSimCountryIso()。那么看下这个函数的注解:

/**

* Returns the ISO country code equivalent of the current registered

* operator's MCC (Mobile Country Code).

*

* Availability: Only when user is registered to a network. Result may be

* unreliable on CDMA networks (use {@link #getPhoneType()} to determine if

* on a CDMA network).

*/

public String getNetworkCountryIso() {

return getNetworkCountryIsoForPhone(getDefaultPhone());

}

翻译过来就是获取当前运营商注册的国家码。而QA的测试机是没有插入sim卡的,那么这个函数返回的CountryCode绝对不是CN(具体返回啥由底层ROM决定)

在测试机插入sim卡之后,TextView的autolink又正确工作了,所以可以确定问题是出在这里。

3.总结

8.1之前的手机,TextView的电话号码匹配和当前手机的地区有关,切换语言时有可能导致号码匹配失效。

大于等于8.1的手机上,号码匹配和当前手机插入的sim卡有关,当使用国外的SIM卡或者不插入SIM卡时,有可能会导致号码匹配失效。

发布评论

评论列表 (0)

  1. 暂无评论