Android 号码匹配联系人问题

blog.csdn.net/u012932409/…

问题背景

最近测试拨号功能测出两个问题

    1. 存入联系人 cc,手机号:1234567. 在拨号盘中输入121234567(*1234567),通话显示会匹配到 联系cc。即只要拨号盘输入的后街与 1234567 相同,就会匹配到 cc.
    1. 存入联系人 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
喜欢就支持一下吧
点赞0 分享