当你在系统通讯录存储8位号码联系人后,呼出时在刚刚存储8位号码前任意补足3位数,
查询到的联系人名称将被模糊匹配为8位号对应名字。举个例子,将 87354321 存储为 哈哈哈,
拨号盘拨打 01087354321,通话记录和拨号界面都会显示 哈哈哈。要想解决这个问题需要了解
系统联系人查询规则,可参考 Android6.0来电号码电话薄名称匹配
整体看下来后发现就是查询 Provider,在 packages/apps/Dialer/java/com/android/incallui/CallerInfoAsyncQuery.java
中调用可传递 selection,不想模糊匹配那直接修改 selection 将 number=实际呼出号码,经过验证发现没有用。
继续往下寻找到 packages/providers/ContactsProvider/src/com/android/providers/contacts/ContactsProvider2.java
case PHONE_LOOKUP: { // Phone lookup cannot be combined with a selection selection = null; selectionArgs = null;
selection 被置为 null 了,难怪不生效。打印实际查询SQL语句如下
near “number”: syntax error (code 1 SQLITE_ERROR): , while compiling: SELECT contacts_view._id AS contact_id, contacts_view.display_name AS display_name, contacts_view.lookup AS lookup, data1 AS number, data4 AS normalized_number, data3 AS label, data2 AS type, contacts_view.photo_uri AS photo_uri, contacts_view.custom_ringtone AS custom_ringtone, contacts_view.send_to_voicemail AS send_to_voicemail FROM raw_contacts JOIN view_contacts contacts_view ON (contacts_view._id = raw_contacts.contact_id), (SELECT data_id, normalized_number, length(normalized_number) as len FROM phone_lookup WHERE (phone_lookup.min_match = ‘1234537’)) AS lookup, data LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id) LEFT OUTER JOIN agg_presence ON (contact_id = agg_presence.presence_contact_id) WHERE (lookup.data_id=data._id AND data.raw_contact_id=raw_contacts._id AND ( lookup.len <= 11 AND substr(‘03087354321’,11 - lookup.len + 1) = lookup.normalized_number OR ( lookup.len > 11 AND substr(lookup.normalized_number,lookup.len + 1 - 11) = ‘03087354321’) )number=?) ORDER BY length(lookup.normalized_number) DESC WHERE (lookup.data_id=data._id AND data.raw_contact_id=raw_contacts._id AND ( lookup.len <= 11 AND substr(‘03087354321’,11 - lookup.len + 1) = lookup.normalized_number OR ( lookup.len > 11 AND substr(lookup.normalized_number,lookup.len + 1 - 11) = ‘03087354321’))) AND ( where number = ‘0308 7354 321’) ORDER BY length(lookup.normalized_number) DESC SELECT contacts_view._id AS contact_id, contacts_view.display_name AS display_name, contacts_view.lookup AS lookup, data1 AS number, data4 AS normalized_number, data3 AS label, data2 AS type, contacts_view.photo_uri AS photo_uri, contacts_view.custom_ringtone AS custom_ringtone, contacts_view.send_to_voicemail AS send_to_voicemail FROM raw_contacts JOIN view_contacts as contacts_view ON (contacts_view._id = raw_contacts.contact_id) JOIN (SELECT data_id,normalized_number FROM phone_lookup WHERE (phone_lookup.min_match = ‘1234537’)) AS lookup ON lookup.data_id=data._id JOIN data ON data.raw_contact_id=raw_contacts._id LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id) LEFT OUTER JOIN agg_presence ON (contact_id = agg_presence.presence_contact_id) WHERE (AND ( lookup.normalized_number = ‘03087354321’)PHONE_NUMBERS_EQUAL(data.data1, ‘0308 7354 321’, 0)) ORDER BY length(lookup.normalized_number) DESC SELECT contacts_view._id AS contact_id, contacts_view.display_name AS display_name, contacts_view.lookup AS lookup, data1 AS number, data4 AS normalized_number, data3 AS label, data2 AS type, contacts_view.photo_uri AS photo_uri, contacts_view.custom_ringtone AS custom_ringtone, contacts_view.send_to_voicemail AS send_to_voicemail FROM raw_contacts JOIN view_contacts as contacts_view ON (contacts_view._id = raw_contacts.contact_id) JOIN (SELECT data_id,normalized_number FROM phone_lookup WHERE (phone_lookup.min_match = ‘1234537’)) AS lookup ON lookup.data_id=data._id JOIN data ON data.raw_contact_id=raw_contacts._id LEFT OUTER JOIN status_updates contacts_status_updates ON (status_update_id=contacts_status_updates.status_update_data_id) LEFT OUTER JOIN agg_presence ON (contact_id = agg_presence.presence_contact_id) WHERE ( ( lookup.normalized_number = ‘03087354321’) ANDPHONE_NUMBERS_EQUAL(data.data1, ‘0308 7354 321’, 0)) ORDER BY length(lookup.normalized_number) Desc
着实很复杂,最终修改如下
// Peek at the results of the first query (which attempts to use fully // normalized and internationalized numbers for comparison). If no results // were returned, fall back to using the SQLite function // phone_number_compare_loose. + qb.appendWhere("AND ( lookup.normalized_number = '"+normalizedNumber+"')"); qb.setStrict(true); boolean foundResult = false; Cursor cursor = doQuery(db, qb, projectionWithNumber, selection, selectionArgs, sortOrder, groupBy, null, limit, cancellationSignal); ......... // Use the fall-back lookup method. qb = new SQLiteQueryBuilder(); qb.setProjectionMap(sPhoneLookupProjectionMap); + qb.appendWhere(" (lookup.normalized_number = '"+normalizedNumber+"') AND "); qb.setStrict(true); // use the raw number instead of the normalized number because // phone_number_compare_loose in SQLite works only with non-normalized // numbers mDbHelper.get().buildFallbackPhoneLookupAndContactQuery(qb, number);