android:autolink="phone",TextView autoLink="phone" 在8.1机器上无效

前言

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

ef39e837de62?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

物流追踪

在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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值