什麼是號碼匹配,個人理解,即判斷兩組號碼是否屬於同一個號碼。在實際使用過程中,接觸到的號碼會涉及到區號,國家編碼以及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。另外這裡還有一個strict 模式:mUseStrictPhoneNumberComparation。關於strict 模式可以直接去OldPhoneNumberUtils.cpp所在目錄查看PHONE_NUMBERS_EQUAL方法實現。自己看了下strict 模式僅僅和泰國有關係,意義不是很大,android本身也基本都是關閉的,大多數情境下都沒有使用strict 模式。
再說說構建資料庫語句時候的號碼匹配。這個號碼匹配位元是在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位一般是不夠用的,各開發人員可以根據自己的需要進行修改。