/* * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.micode.notes.data; import android.content.Context; import android.database.Cursor; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Data; import android.telephony.PhoneNumberUtils; import android.util.Log; import java.util.HashMap; /** * 联系人查询工具类 * * 功能:根据电话号码查询对应的联系人姓名 * 特点: * 1. 使用内存缓存提升查询效率 * 2. 支持电话号码最小匹配规则(国际号码优化) * 3. 处理联系人数据库查询异常 */ public class Contact { // 联系人缓存:电话号码 -> 联系人姓名 private static HashMap sContactCache; private static final String TAG = "Contact"; // 日志标签 /** * 联系人查询的SQL选择语句 * * 结构说明: * 1. 使用 PHONE_NUMBERS_EQUAL 进行号码匹配(考虑格式化差异) * 2. 限定数据类型为电话类型 (Phone.CONTENT_ITEM_TYPE) * 3. 通过子查询关联 phone_lookup 表实现快速索引 * 4. "+" 是占位符,将被替换为最小匹配长度 */ private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" + Phone.NUMBER + ",?) AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" + " AND " + Data.RAW_CONTACT_ID + " IN " + "(SELECT raw_contact_id " + " FROM phone_lookup" + " WHERE min_match = '+')"; // '+' 将被实际的最小匹配值替换 /** * 根据电话号码获取联系人姓名 * * @param context 上下文对象(用于访问ContentResolver) * @param phoneNumber 要查询的电话号码 * @return 联系人姓名,若未找到则返回null */ public static String getContact(Context context, String phoneNumber) { // 初始化缓存 if (sContactCache == null) { sContactCache = new HashMap(); } // 首先检查缓存 if (sContactCache.containsKey(phoneNumber)) { return sContactCache.get(phoneNumber); } // 生成最小匹配长度(处理国际号码) String minMatch = PhoneNumberUtils.toCallerIDMinMatch(phoneNumber); // 构建完整查询语句 String selection = CALLER_ID_SELECTION.replace("+", minMatch); // 执行内容提供者查询 Cursor cursor = context.getContentResolver().query( Data.CONTENT_URI, // 联系人数据URI new String[]{Phone.DISPLAY_NAME}, // 只需返回姓名字段 selection, // 动态生成的查询条件 new String[]{phoneNumber}, // 查询参数(实际号码) null); // 无排序要求 if (cursor != null && cursor.moveToFirst()) { try { // 读取第一条结果的姓名 String name = cursor.getString(0); // 加入缓存 sContactCache.put(phoneNumber, name); return name; } catch (IndexOutOfBoundsException e) { Log.e(TAG, "Cursor字段访问错误: " + e.toString()); return null; } finally { // 确保关闭游标 cursor.close(); } } else { // 无匹配结果日志 Log.d(TAG, "未找到匹配的联系人号码: " + phoneNumber); return null; } } }