问题背景
最近测试拨号功能测出两个问题
-
- 存入联系人 cc,手机号:1234567. 在拨号盘中输入121234567(*1234567),通话显示会匹配到 联系cc。即只要拨号盘输入的后街与 1234567 相同,就会匹配到 cc.
-
- 存入联系人 ee,手机号:133 1232 1231.拨号盘中输入 * 133 1232 1231。通话显示会匹配到联系人 ee.
一开始将问题1解决了,之后问题2也随之而来。
解决方案
方案1
针对问题1,通过百度,找到了一个解决方案,修改 PhoneNumberUtils.java
中的 MIN_MATCH
为11,设置最低号码匹配为11位。在此种情况下,低于11位的号码,必须相等才会匹配。
frameworks/base/telephony/java/android/telephony/PhoneNumberUtils.java
//static final int MIN_MATCH = 7;
static final int MIN_MATCH = 11;
public static boolean compare(Context context, String a, String b) {
boolean useStrict = context.getResources().getBoolean(
com.android.internal.R.bool.config_use_strict_phone_number_comparation);
return compare(a, b, useStrict);
}
/**
* @hide only for testing.
*/
public static boolean compare(String a, String b, boolean useStrictComparation) {
return (useStrictComparation ? compareStrictly(a, b) : compareLoosely(a, b));
}
public static boolean compareLoosely(String a, String b) {
int ia, ib;
int matched;
int numNonDialableCharsInA = 0;
int numNonDialableCharsInB = 0;
if (a == null || b == null) return a == b;
if (a.length() == 0 || b.length() == 0) {
return false;
}
ia = indexOfLastNetworkChar (a);
ib = indexOfLastNetworkChar (b);
matched = 0;
while (ia >= 0 && ib >=0) {
char ca, cb;
boolean skipCmp = false;
ca = a.charAt(ia);
if (!isDialable(ca)) {
ia--;
skipCmp = true;
numNonDialableCharsInA++;
}
cb = b.charAt(ib);
if (!isDialable(cb)) {
ib--;
skipCmp = true;
numNonDialableCharsInB++;
}
if (!skipCmp) {
if (cb != ca && ca != WILD && cb != WILD) {
break;
}
ia--; ib--; matched++;
}
}
if (matched < MIN_MATCH) {
int effectiveALen = a.length() - numNonDialableCharsInA;
int effectiveBLen = b.length() - numNonDialableCharsInB;
// if the number of dialable chars in a and b match, but the matched chars < MIN_MATCH,
// treat them as equal (i.e. 404-04 and 40404)
if (effectiveALen == effectiveBLen && effectiveALen == matched) {
return true;
}
return false;
}
// At least one string has matched completely;
if (matched >= MIN_MATCH && (ia < 0 || ib < 0)) {
return true;
}
/*
* Now, what remains must be one of the following for a
* match:
*
* - a '+' on one and a '00' or a '011' on the other
* - a '0' on one and a (+,00)<country code> on the other
* (for this, a '0' and a '00' prefix would have succeeded above)
*/
if (matchIntlPrefix(a, ia + 1)
&& matchIntlPrefix (b, ib +1)
) {
return true;
}
if (matchTrunkPrefix(a, ia + 1)
&& matchIntlPrefixAndCC(b, ib +1)
) {
return true;
}
if (matchTrunkPrefix(b, ib + 1)
&& matchIntlPrefixAndCC(a, ia +1)
) {
return true;
}
return false;
}
复制代码
然后这种方法显然是无法问题2的。
方案2
事实上,对于解决这个问题还有个更好的方法。事实上,官方代码本身就定义了一个是否开启严格匹配模式的开关,这个开关默认是关闭的。
配置文件:frameworks/base/core/res/res/values/config.xml
<bool name="config_use_strict_phone_number_comparation">false</bool>
复制代码
如上默认值为 false
,改为 true
就行了。如此就会用严格模式去进行匹配了。
public static boolean compareStrictly(String a, String b, boolean acceptInvalidCCCPrefix) {
if (a == null || b == null) {
return a == b;
} else if (a.length() == 0 && b.length() == 0) {
return false;
}
int forwardIndexA = 0;
int forwardIndexB = 0;
CountryCallingCodeAndNewIndex cccA =
tryGetCountryCallingCodeAndNewIndex(a, acceptInvalidCCCPrefix);
CountryCallingCodeAndNewIndex cccB =
tryGetCountryCallingCodeAndNewIndex(b, acceptInvalidCCCPrefix);
boolean bothHasCountryCallingCode = false;
boolean okToIgnorePrefix = true;
boolean trunkPrefixIsOmittedA = false;
boolean trunkPrefixIsOmittedB = false;
if (cccA != null && cccB != null) {
if (cccA.countryCallingCode != cccB.countryCallingCode) {
// Different Country Calling Code. Must be different phone number.
return false;
}
// When both have ccc, do not ignore trunk prefix. Without this,
// "+81123123" becomes same as "+810123123" (+81 == Japan)
okToIgnorePrefix = false;
bothHasCountryCallingCode = true;
forwardIndexA = cccA.newIndex;
forwardIndexB = cccB.newIndex;
} else if (cccA == null && cccB == null) {
// When both do not have ccc, do not ignore trunk prefix. Without this,
// "123123" becomes same as "0123123"
okToIgnorePrefix = false;
} else {
if (cccA != null) {
forwardIndexA = cccA.newIndex;
} else {
int tmp = tryGetTrunkPrefixOmittedIndex(b, 0);
if (tmp >= 0) {
forwardIndexA = tmp;
trunkPrefixIsOmittedA = true;
}
}
if (cccB != null) {
forwardIndexB = cccB.newIndex;
} else {
int tmp = tryGetTrunkPrefixOmittedIndex(b, 0);
if (tmp >= 0) {
forwardIndexB = tmp;
trunkPrefixIsOmittedB = true;
}
}
}
int backwardIndexA = a.length() - 1;
int backwardIndexB = b.length() - 1;
while (backwardIndexA >= forwardIndexA && backwardIndexB >= forwardIndexB) {
boolean skip_compare = false;
final char chA = a.charAt(backwardIndexA);
final char chB = b.charAt(backwardIndexB);
if (isSeparator(chA)) {
backwardIndexA--;
skip_compare = true;
}
if (isSeparator(chB)) {
backwardIndexB--;
skip_compare = true;
}
if (!skip_compare) {
if (chA != chB) {
return false;
}
backwardIndexA--;
backwardIndexB--;
}
}
if (okToIgnorePrefix) {
if ((trunkPrefixIsOmittedA && forwardIndexA <= backwardIndexA) ||
!checkPrefixIsIgnorable(a, forwardIndexA, backwardIndexA)) {
if (acceptInvalidCCCPrefix) {
// Maybe the code handling the special case for Thailand makes the
// result garbled, so disable the code and try again.
// e.g. "16610001234" must equal to "6610001234", but with
// Thailand-case handling code, they become equal to each other.
//
// Note: we select simplicity rather than adding some complicated
// logic here for performance(like "checking whether remaining
// numbers are just 66 or not"), assuming inputs are small
// enough.
return compare(a, b, false);
} else {
return false;
}
}
if ((trunkPrefixIsOmittedB && forwardIndexB <= backwardIndexB) ||
!checkPrefixIsIgnorable(b, forwardIndexA, backwardIndexB)) {
if (acceptInvalidCCCPrefix) {
return compare(a, b, false);
} else {
return false;
}
}
} else {
// In the US, 1-650-555-1234 must be equal to 650-555-1234,
// while 090-1234-1234 must not be equal to 90-1234-1234 in Japan.
// This request exists just in US (with 1 trunk (NDD) prefix).
// In addition, "011 11 7005554141" must not equal to "+17005554141",
// while "011 1 7005554141" must equal to "+17005554141"
//
// In this comparison, we ignore the prefix '1' just once, when
// - at least either does not have CCC, or
// - the remaining non-separator number is 1
boolean maybeNamp = !bothHasCountryCallingCode;
while (backwardIndexA >= forwardIndexA) {
final char chA = a.charAt(backwardIndexA);
if (isDialable(chA)) {
if (maybeNamp && tryGetISODigit(chA) == 1) {
maybeNamp = false;
} else {
return false;
}
}
backwardIndexA--;
}
while (backwardIndexB >= forwardIndexB) {
final char chB = b.charAt(backwardIndexB);
if (isDialable(chB)) {
if (maybeNamp && tryGetISODigit(chB) == 1) {
maybeNamp = false;
} else {
return false;
}
}
backwardIndexB--;
}
}
return true;
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END