lihao
pic3v8nmu 7 months ago
parent 199d921862
commit 0b7188336f

139
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<String, String> 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<String, String>();
}
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<String, String> 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 version="1.0" encoding="UTF-8"?>-// 这是XML文档的标准声明头部用于指定当前XML文件所遵循的XML版本号是1.0以及采用UTF - 8编码格式。UTF - 8通用性强能支持全球多种语言字符确保不同语言环境下内容正确解析与显示。
<!-- Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) Licensed under the Apache License, Version 2.0 (the "License"); you may n“ot 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.--> 这是一段XML注释解释代码的版权信息。说明代码版权归MiCode开源社区时间在2010到2011年 基于Apache 2.0许可证开源,还详细介绍了该许可证下使用代码的权限、限制,以及获取许可证副本的网址。<selector xmlns:android="http://schemas.android.com/apk/res/android">-//  <selector> 是Android开发中的一个XML标签用于创建资源选择器比如可针对控件不同状态如按下、聚焦、默认等来选择不同的样式。 xmlns:android 定义了Android系统相关的XML命名空间后续带有 android 前缀的属性会依据这个命名空间所指向的Android资源规范来解析。
<item android:color="#50000000" />-  <item> 是 <selector> 的子元素用于定义选择器中的一个选项。 android:color 是Android命名空间下的属性用于指定颜色 #50000000  是ARGB格式的颜色值其中 50 代表透明度50% 透明后面的 000000 表示颜色这里是黑色意味着该选项对应的是某种半透明黑色的设置。
</selector>与开头的 <selector> 标签配对用于闭合 selector 元素标志着这个选择器资源定义的结束。
<!-- 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. -->- 这是一段XML注释主要用于说明版权信息。告知代码的版权归属于MiCode开源社区时间跨度为2010 - 2011年采用Apache License 2.0授权,还给出了许可证获取链接,并强调使用代码需遵循该许可,同时说明了软件按“原样”分发,无额外明示或暗示的保障条款。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">-  <LinearLayout> 这是一个线性布局容器在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" :指定线性布局内的子视图按垂直方向排列。
<TextView android:id="@+id/account_dialog_title" style="?android:attr/textAppearanceMedium" android:singleLine="true" android:ellipsize="end" android:gravity="center" android:layout_marginTop="-2.7dip" android:layout_marginBottom="-2.7dip" android:layout_width="fill_parent" android:layout_height="wrap_content"/>-  <TextView> :用于在界面上显示文本内容的视图控件。
-  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" :文本视图高度自适应文本内容高度。
<TextView android:id="@+id/account_dialog_subtitle" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="5dip" android:layout_marginBottom="1dip" android:gravity="center"/>
</LinearLayout>- 另一个 <TextView> 控件:
-  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 version="1.0" encoding="UTF-8"?>//这是 XML 声明,表明这份 XML 文档遵循 XML 1.0 标准,使用的字符编码是 UTF-8。UTF-8 是一种常用编码,能表示世界上绝大多数的字符,保证文档内容在不同系统间的兼容性。
<!-- 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.--> - //这是一段注释内容,用于说明版权信息。告知代码的版权归属是 MiCode 开源社区,时间跨度为 2010 - 2011 年,并且声明该代码基于 Apache 2.0 许可证授权,详细解释了使用该代码的一些许可条款和条件
<selector xmlns:android="http://schemas.android.com/apk/res/android">  <selector>  是 Android 系统里用于定义状态选择器的标签。// xmlns:android  是一个 XML 命名空间声明 http://schemas.android.com/apk/res/android  指明了 Android 系统提供的资源相关的 XML 命名空间,后续使用到的  android  前缀的属性,都来自这个命名空间。借助这个命名空间,才能使用 Android 特有的属性来定制这个选择器
<item android:color="#50000000" />--  <item>  //是  <selector>  的子元素。这里设置了一个属性  android:color 其值为  #50000000 这是一个颜色值在 Android 里使用十六进制来表示颜色,前两位数字(这里是  50 表示透明度后面六位数字 000000 表示颜色 000000  代表黑色,整体表示一个半透明的黑色。这个  <item>  元素单独存在时,大概率用于某些默认状态下的颜色设定,比如在状态选择器里,如果没有其他匹配的状态,就会应用这个颜色。
</selector>-。-// 闭合  selector  标签,与开头的  <selector>  对应,完成了这个选择器的 XML 定义。
<!-- 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. -->- 这是一段XML注释用于声明版权信息这段代码版权归MiCode开源社区时间跨度2010 - 2011年基于Apache License 2.0授权。它告知使用者,要获取、使用这份代码,需遵循该许可证的相关规定,同时说明了授权软件的分发状态。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content">-  <LinearLayout> 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" :布局高度自适应其内部子视图的总高度。
<NumberPicker android:id="@+id/date" android:layout_width="120dip" android:layout_height="wrap_content" android:focusable="true" android:focusableInTouchMode="true"/>-  <NumberPicker> :这是一个数字选择器控件,用于让用户选择数字。
-  android:id="@+id/date" 给该数字选择器分配一个唯一ID方便在代码中引用它。
-  android:layout_width="120dip" 设置宽度为120设备独立像素 ,确定了它在布局中的横向尺寸。
-  android:layout_height="wrap_content" :高度自适应内容,也就是会根据数字选择器的内容多少来调整自身高度。
-  android:focusable="true" :表示该控件可以获取焦点,能响应键盘等输入设备。
-  android:focusableInTouchMode="true" :在触摸模式下也可以获取焦点,方便触屏操作。
<NumberPicker android:id="@+id/hour" android:layout_width="50dip" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:focusable="true" android:focusableInTouchMode="true"/>
<NumberPicker android:id="@+id/minute" android:layout_width="50dip" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:focusable="true" android:focusableInTouchMode="true"/>- 第二个 <NumberPicker> 
-  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" :和前面一样,用于设置焦点相关属性。<NumberPicker android:id="@+id/amPm" android:layout_width="50dip" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:focusable="true" android:focusableInTouchMode="true"/>- 第四个 <NumberPicker> 也是数字选择器通过ID区分大概率用于选择上午、下午AM/PM属性设置与其他几个数字选择器一致用于布局间隔与焦点获取。
</LinearLayout>
Loading…
Cancel
Save