diff --git a/Lihao b/Lihao new file mode 100644 index 0000000..a919ed0 --- /dev/null +++ b/Lihao @@ -0,0 +1,139 @@ +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; + +public class Contact { + private static HashMap sContactCache; + private static final String TAG = "Contact"; + + 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 + */ + public static String getContact(Context context, String phoneNumber) { + if(sContactCache == null) { + sContactCache = new HashMap(); + } + + if(sContactCache.containsKey(phoneNumber)) { + return sContactCache.get(phoneNumber); + } +// + String selection = CALLER_ID_SELECTION.replace("+", + PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); + Cursor cursor = context.getContentResolver().query( + Data.CONTENT_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 get string error " + e.toString()); + return null; + } finally { + cursor.close(); + } + } else { + Log.d(TAG, "No contact matched with number:" + phoneNumber); + return null; + } + } +} +-  package net.micode.notes.data; :声明了该Java类所在的包名,用于组织和管理相关的类,方便项目的模块化构建。 +- 一系列 import 语句: +-  import android.content.Context; :引入 Context 类,它提供了访问应用程序全局信息的入口,像是访问资源、启动服务等操作都离不开它。 +-  import android.database.Cursor; :导入 Cursor 类,用于遍历数据库查询结果集,在从Android系统的联系人数据库查询数据时会用到。 +-  import android.provider.ContactsContract.CommonDataKinds.Phone;  与  import android.provider.ContactsContract.Data; :引入与Android联系人数据存储相关的类,以便访问联系人数据库中的电话号码、联系人姓名等信息。 +-  import android.telephony.PhoneNumberUtils; :用于处理电话号码相关的实用工具类,比如格式化电话号码。 +-  import android.util.Log; :导入日志记录类,方便在代码运行时输出调试信息、错误信息等。 +-  import java.util.HashMap; :引入 HashMap 类,用于创建键值对形式的缓存,存储电话号码和对应的联系人姓名。 +-  public class Contact :定义了一个公共类 Contact ,外界其他类可以访问它。 +-  private static HashMap sContactCache; :声明一个静态的 HashMap ,用于缓存已经查询过的电话号码和对应的联系人姓名, private 修饰表示只能在本类内部访问。 +-  private static final String TAG = "Contact"; :定义一个静态常量字符串,作为日志输出时的标签,方便区分是哪个类输出的日志。 +-  private static final String CALLER_ID_SELECTION :定义一个静态常量字符串,它构建了一个SQL查询语句的 WHERE 子句,用于从联系人数据库中查找匹配给定电话号码的联系人记录 。 +-  public static String getContact(Context context, String phoneNumber) :定义了一个静态公共方法,接收一个 Context 对象和一个电话号码字符串作为参数,目的是根据电话号码获取对应的联系人姓名。 +- 首先检查 sContactCache 是否为空,如果为空就初始化它,创建一个新的 HashMap 。 +- 接着检查缓存中是否已经存在该电话号码对应的联系人姓名,如果存在则直接返回缓存中的值。 +-  String selection = CALLER_ID_SELECTION.replace("+", PhoneNumberUtils.toCallerIDMinMatch(phoneNumber)); :替换之前定义的查询语句中的 + 符号,利用 PhoneNumberUtils 工具类生成更匹配当前电话号码的查询条件。 +-  Cursor cursor = context.getContentResolver().query(...) :使用 Context 对象的 getContentResolver 方法获取一个 ContentResolver ,并发起一个数据库查询。查询的目标是 Data.CONTENT_URI ,也就是联系人数据库相关的内容URI,只选取 Phone.DISPLAY_NAME 列,查询条件是前面生成的 selection ,参数是给定的电话号码, null 表示不使用排序规则。 + - 如果 Cursor 不为空且能移动到第一条记录,说明找到了匹配的联系人: +- 尝试获取查询结果的第一列数据,也就是联系人姓名,存入缓存,并返回该姓名。 +- 如果捕获到 IndexOutOfBoundsException 异常,说明获取列数据出错,记录错误日志并返回 null ,同时确保最后关闭 Cursor 。 +- 如果 Cursor 为空或者无法移动到第一条记录,说明没找到匹配的联系人,记录一条调试日志并返回 null 。 + -// 这是XML文档的标准声明头部,用于指定当前XML文件所遵循的XML版本号是1.0,以及采用UTF - 8编码格式。UTF - 8通用性强,能支持全球多种语言字符,确保不同语言环境下内容正确解析与显示。 + 这是一段XML注释,解释代码的版权信息。说明代码版权归MiCode开源社区,时间在2010到2011年 ,基于Apache 2.0许可证开源,还详细介绍了该许可证下使用代码的权限、限制,以及获取许可证副本的网址。-//   是Android开发中的一个XML标签,用于创建资源选择器,比如可针对控件不同状态(如按下、聚焦、默认等)来选择不同的样式。 xmlns:android 定义了Android系统相关的XML命名空间,后续带有 android 前缀的属性,会依据这个命名空间所指向的Android资源规范来解析。 + -   是  的子元素,用于定义选择器中的一个选项。 android:color 是Android命名空间下的属性,用于指定颜色, #50000000  是ARGB格式的颜色值,其中 50 代表透明度(50% 透明),后面的 000000 表示颜色,这里是黑色,意味着该选项对应的是某种半透明黑色的设置。 +与开头的  标签配对,用于闭合 selector 元素,标志着这个选择器资源定义的结束。 + +- 这是一段XML注释,主要用于说明版权信息。告知代码的版权归属于MiCode开源社区,时间跨度为2010 - 2011年,采用Apache License 2.0授权,还给出了许可证获取链接,并强调使用代码需遵循该许可,同时说明了软件按“原样”分发,无额外明示或暗示的保障条款。 +-   :这是一个线性布局容器,在Android UI开发中用于按水平或垂直方向排列子视图。 +-  xmlns:android="http://schemas.android.com/apk/res/android" :定义了Android XML命名空间,通过它才能使用Android系统内置的各种属性。 +-  android:layout_width="fill_parent" :设置该线性布局的宽度占满父容器的宽度 , fill_parent 是早期写法,现在常用 match_parent ,效果相同。 +-  android:layout_height="fill_parent" :让布局的高度占满父容器的高度。 +-  android:orientation="vertical" :指定线性布局内的子视图按垂直方向排列。 +-   :用于在界面上显示文本内容的视图控件。 +-  android:id="@+id/account_dialog_title" :为该TextView分配一个唯一标识符,后续在代码中可以通过这个ID来引用它。 @+  表示创建一个新的资源ID。 +-  style="?android:attr/textAppearanceMedium" :应用了Android系统内置的中等文本外观样式。 ?  表示引用主题属性。 +-  android:singleLine="true" :强制文本在单行内显示。 +-  android:ellipsize="end" :当文本内容超出视图宽度时,在末尾显示省略号。 +-  android:gravity="center" :让文本在视图内居中对齐。 +-  android:layout_marginTop="-2.7dip" :设置视图顶部的外边距为 -2.7dp,负值的外边距有时用于微调布局,让视图更紧凑。 +-  android:layout_marginBottom="-2.7dip" :设置视图底部的外边距为 -2.7dp。 +-  android:layout_width="fill_parent" :文本视图宽度占满父容器宽度。 +-  android:layout_height="wrap_content" :文本视图高度自适应文本内容高度。 + +- 另一个  控件: +-  android:id="@+id/account_dialog_subtitle" :赋予该TextView一个新的ID。 +-  android:layout_width="fill_parent" :宽度占满父容器。 +-  android:layout_height="wrap_content" :高度自适应内容。 +-  android:layout_marginTop="5dip" :设置距离上方视图的外边距是5dp,使该视图与上面的视图有一定间隔。 +-  android:layout_marginBottom="1dip" :设置距离下方视图的外边距是1dp。 +-  android:gravity="center" :文本在视图内居中显示。 +//这是 XML 声明,表明这份 XML 文档遵循 XML 1.0 标准,使用的字符编码是 UTF-8。UTF-8 是一种常用编码,能表示世界上绝大多数的字符,保证文档内容在不同系统间的兼容性。 + - //这是一段注释内容,用于说明版权信息。告知代码的版权归属是 MiCode 开源社区,时间跨度为 2010 - 2011 年,并且声明该代码基于 Apache 2.0 许可证授权,详细解释了使用该代码的一些许可条款和条件 +    是 Android 系统里用于定义状态选择器的标签。// xmlns:android  是一个 XML 命名空间声明, http://schemas.android.com/apk/res/android  指明了 Android 系统提供的资源相关的 XML 命名空间,后续使用到的  android  前缀的属性,都来自这个命名空间。借助这个命名空间,才能使用 Android 特有的属性来定制这个选择器 + + --    //是    的子元素。这里设置了一个属性  android:color ,其值为  #50000000 ,这是一个颜色值,在 Android 里使用十六进制来表示颜色,前两位数字(这里是  50 )表示透明度,后面六位数字( 000000 )表示颜色, 000000  代表黑色,整体表示一个半透明的黑色。这个    元素单独存在时,大概率用于某些默认状态下的颜色设定,比如在状态选择器里,如果没有其他匹配的状态,就会应用这个颜色。 +-。-// 闭合  selector  标签,与开头的    对应,完成了这个选择器的 XML 定义。 +- 这是一段XML注释,用于声明版权信息:这段代码版权归MiCode开源社区,时间跨度2010 - 2011年,基于Apache License 2.0授权。它告知使用者,要获取、使用这份代码,需遵循该许可证的相关规定,同时说明了授权软件的分发状态。 +-   :Android布局容器,用来组织子视图。 +-  xmlns:android="http://schemas.android.com/apk/res/android" :定义Android命名空间,有了它才能引用Android系统提供的属性。 +-  android:orientation="horizontal" :指定子视图按水平方向排列。 +-  android:layout_gravity="center_horizontal" :让此线性布局在父容器中水平居中。 +-  android:layout_width="wrap_content" :布局宽度自适应其内部子视图的总宽度。 +-  android:layout_height="wrap_content" :布局高度自适应其内部子视图的总高度。 +-   :这是一个数字选择器控件,用于让用户选择数字。 +-  android:id="@+id/date" :给该数字选择器分配一个唯一ID,方便在代码中引用它。 +-  android:layout_width="120dip" :设置宽度为120设备独立像素 ,确定了它在布局中的横向尺寸。 +-  android:layout_height="wrap_content" :高度自适应内容,也就是会根据数字选择器的内容多少来调整自身高度。 +-  android:focusable="true" :表示该控件可以获取焦点,能响应键盘等输入设备。 +-  android:focusableInTouchMode="true" :在触摸模式下也可以获取焦点,方便触屏操作。 + +- 第二个  : +-  android:id="@+id/hour" :定义ID。 +-  android:layout_width="50dip" :宽度设为50设备独立像素。 +-  android:layout_height="wrap_content" :高度自适应。 +-  android:layout_marginLeft="5dip" :设置它与左边相邻视图的间距为5设备独立像素,用于布局间隔。 +-  android:focusable="true"  与  android:focusableInTouchMode="true" :和前面一样,用于设置焦点相关属性。- 第四个  :也是数字选择器,通过ID区分,大概率用于选择上午、下午(AM/PM),属性设置与其他几个数字选择器一致,用于布局间隔与焦点获取。 + \ No newline at end of file