詳解android的號碼匹配

    什麼是號碼匹配,個人理解,即判斷兩組號碼是否屬於同一個號碼。在實際使用過程中,接觸到的號碼會涉及到區號,國傢編碼以及IP號碼等,這個時候就用到瞭號碼匹配。兩個內容不一樣的號碼,如+86***和17951***,是不是同一個號碼。就需要軟件判斷是否同一個號碼。手機裡面涉及號碼匹配的場景很多,打電話發短信都要用到。和前面的+86***和17951***兩個號碼所示,號碼匹配是從後往前進行比較的,可以猜測一個標準號碼的附加號碼都是加在前面的。

        根據匹配數據來源可以將號碼匹配分為一下兩種:
        1.同一個應用內的號碼匹配:在一個應用內判斷兩個號碼是否是同一個號碼,根據結果將記錄合並或者分開。典型場景如:通話記錄是否合並,新發送或者新接收的短信是新建會話還是存入已知會話。
        2.同聯系人應用進行號碼匹配:一個應用去聯系人數據庫裡面查詢,獲取號碼的其他數據。一般每個涉及號碼的應用都會有一個自己的數據庫的表,用來存儲號碼上的信息。應用第一次收到號碼都會查詢聯系人的數據庫,獲得這個號碼的詳細信息:如姓名等。典型的場景有:發短信和打電話時候輸入瞭號碼自動匹配上瞭號碼對應的聯系人姓名,一段文字裡面的號碼是否在當前手機中有。

        在android原生系統上,大致可以根據前面介紹,將其號碼匹配的實現方案分為兩種:
        1.在數據庫增加PHONE_NUMBERS_EQUAL方法,進行SQL級別的匹配查詢,這個方法有三個參數,兩個是號碼,還有一個是否是嚴格匹配。查看2.3.5的android源碼,這個嚴格匹配和泰國有關系……所以一般這個參數都是false,即不執行嚴格號碼匹配。
        2.在構建數據庫的查詢語句上,進行號碼匹配。一般這種情況都會進行號碼的從後往前的截斷,直接判斷截斷的數據是否相等。

        號碼匹配是後往前匹配的,如果後面連續N個數字相等的話,就認為是同一個號碼。這裡的N,即是N位號碼匹配。google自帶的兩個號碼匹配都是7位號碼匹配。下面來根據實例進行講解。先說說數據庫上的PHONE_NUMBERS_EQUAL方法,直接去看telephonyprovider裡面的一個方法:

 

private long getSingleAddressId(String address) { 
    …… 
    if (!isPhoneNumber) { 
        selectionArgs = new String[] { refinedAddress }; 
    } else { 
        selection += " OR PHONE_NUMBERS_EQUAL(address, ?, " + 
                    (mUseStrictPhoneNumberComparation ? 1 : 0) + ")"; 
        selectionArgs = new String[] { refinedAddress, refinedAddress }; 
    } 

    private long getSingleAddressId(String address) {
        ……
        if (!isPhoneNumber) {
            selectionArgs = new String[] { refinedAddress };
        } else {
            selection += " OR PHONE_NUMBERS_EQUAL(address, ?, " +
                        (mUseStrictPhoneNumberComparation ? 1 : 0) + ")";
            selectionArgs = new String[] { refinedAddress, refinedAddress };
        }

如代碼所示,構建SQL語句時候直接使用瞭PHONE_NUMBERS_EQUAL方法,進行數據庫級別的比較,這裡的號碼匹配位數是7位,在OldPhoneNumberUtils.cpp文件中,定義語句是static int MIN_MATCH = 7。另外這裡還有一個嚴格模式:mUseStrictPhoneNumberComparation。關於嚴格模式可以直接去OldPhoneNumberUtils.cpp所在目錄查看PHONE_NUMBERS_EQUAL方法實現。自己看瞭下嚴格模式僅僅和泰國有關系,意義不是很大,android本身也基本都是關閉的,大多數場景下都沒有使用嚴格模式。

        再說說構建數據庫語句時候的號碼匹配。這個號碼匹配位數是在PhoneNumberUtils.java文件裡面。定義代碼如下:static final int MIN_MATCH = 7。查看PhoneNumberUtils.java的公有方法public static String toCallerIDMinMatch(String)在contact數據庫裡面的調用,就可以看到:聯系人數據庫在每次新增加一個號碼的時候,都會增加一個字段,即後7位號碼,用來幫助查詢。在構建查詢的SQL語句時候,也會調用public static String toCallerIDMinMatch(String)方法,截取查詢號碼的後7位。典型代碼如下:

 

public void buildPhoneLookupAndContactQuery( 
        SQLiteQueryBuilder qb, String normalizedNumber, String numberE164) { 
    String minMatch = PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber); 
    StringBuilder sb = new StringBuilder(); 
    appendPhoneLookupTables(sb, minMatch, true); 
    qb.setTables(sb.toString()); 
 
    sb = new StringBuilder(); 
    appendPhoneLookupSelection(sb, normalizedNumber, numberE164); 
    qb.appendWhere(sb.toString()); 
} 

    public void buildPhoneLookupAndContactQuery(
            SQLiteQueryBuilder qb, String normalizedNumber, String numberE164) {
        String minMatch = PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber);
        StringBuilder sb = new StringBuilder();
        appendPhoneLookupTables(sb, minMatch, true);
        qb.setTables(sb.toString());

        sb = new StringBuilder();
        appendPhoneLookupSelection(sb, normalizedNumber, numberE164);
        qb.appendWhere(sb.toString());
    }   

     到這裡google原生的號碼匹配基本介紹結束。原生的是7位號碼匹配,考慮到我國固定電話長度是8位,手機號碼長度是11位,7位一般是不夠用的,各開發者可以根據自己的需要進行修改。

 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *