/* * 版权所有 (c) 2010-2011,MiCode 开源社区 (www.micode.net) * 根据 Apache 许可证 2.0 版本("许可证")授权; * 除非符合许可证的规定,否则不得使用本文件。 * 您可以从以下网址获取许可证副本: * http://www.apache.org/licenses/LICENSE-2.0 * 除非适用法律要求或书面同意,本软件按"原样"分发, * 没有任何明示或暗示的保证或条件。 * 详见许可证中规定的权限和限制。 * (注:这是一份标准的Apache许可证2.0版本的开源声明) */ // 声明该类所在的包 package net.micode.notes.data; // 导入android.content 包下的Context类,用于访问应用程序资源和类 import android.content.Context; // 导入android.database 包下的Cursor类,用于遍历查询结果集 import android.database.Cursor; // 导入android.provider.ContactsContract.CommonDataKinds 包下的Phone类,用于访问联系人的电话号码相关信息 import android.provider.ContactsContract.CommonDataKinds.Phone; // 导入android.provider.ContactsContract 包下的Data类,用于访问联系人的数据 import android.provider.ContactsContract.Data; // 导入android.telephony 包下的PhoneNumberUtils类,用于处理电话号码相关操作 import android.telephony.PhoneNumberUtils; // 导入android.util 包下的Log类,用于日志记录 import android.util.Log; // 导入java.util 包下的HashMap类,用于存储键值对 import java.util.HashMap; // 定义一个名为Contact的公共类 public class Contact { // 声明一个静态的HashMap对象sContactCache,用于缓存电话号码和对应的联系人姓名 private static HashMap sContactCache; // 定义一个静态常量TAG,用于日志标记 private static final String TAG = "Contact"; // 定义一个静态常量CALLER_ID_SELECTION,用于构建查询联系人的SQL选择语句 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 上下文对象,用于访问内容解析器 * @param phoneNumber 要查询的电话号码 * @return 联系人姓名,如果未找到则返回null */ public static String getContact(Context context, String phoneNumber) { // 检查sContactCache是否为空,如果为空则进行初始化 if(sContactCache == null) { sContactCache = new HashMap<>(); } // 检查sContactCache中是否已经包含该电话号码 if(sContactCache.containsKey(phoneNumber)) { // 如果包含,则直接从缓存中获取联系人姓名并返回 return sContactCache.get(phoneNumber); } // 替换CALLER_ID_SELECTION中的占位符"+"为电话号码的最小匹配格式 String selection = CALLER_ID_SELECTION.replace("+", PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); // 使用上下文的内容解析器进行查询操作 Cursor cursor = context.getContentResolver().query( // 查询的内容URI Data.CONTENT_URI, // 查询要返回的列,这里只需要联系人的显示名称 new String [] { Phone.DISPLAY_NAME }, // 查询的选择条件 selection, // 选择条件中的参数 new String[] { phoneNumber }, // 排序规则,这里为null表示不排序 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 get string error " + e.toString()); // 出现异常则返回null return null; } finally { // 无论是否出现异常,最后都要关闭游标 cursor.close(); } } else { // 如果游标为空或无法移动到第一行,记录未找到匹配联系人的日志 Log.d(TAG, "No contact matched with number:" + phoneNumber); // 返回null表示未找到匹配的联系人 return null; } } }