一、目标。
通过内容解析器获取手机联系人信息,并采用自定义的样式显示。
为了便于介绍和重复使用,重新建立一个”读取联系人“工程。
二、代码实现。
1、新建工程,取名为”读取联系人“。在布局文件(activity_main.xml)中,采用ListView组件(其ID为select_contact)。
布局文件代码:
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 tools:context=".MainActivity" > 6 7 <ListView 8 android:id="@+id/select_contact" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" /> 11 12 </RelativeLayout>
2、在主程序中实例化ListView组件(取名select_contact),并通过findViewById()方法找到布局文件中的ListView对象。select_contact对象需要通过适配器的方法(setAdapter(ListAdapter adapter))将相关数据填充进去,其中ListAdapter adapter采用SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)。而SimpleAdapter中的第二个参数List就是需要显示的数据,因此需要通过自定义的方法(取名getContactInfo())获取手机中联系人的信息并形成一个List集合。
3、在主程序中新建获取手机联系人信息的方法(取名getContactInfo()),返回值类型为List<Map<String, String>>。在该方法中:
①.通过getContentResolver()得到一个内容解析器(ContentResolver)对象,取名(resolver)。由于需要读取手机联系人,因此需要获取权限(android.permission.READ_CONTACTS)。
②.利用内容解析器的query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)方法查找手机里联系人数据内的相关数据,参数中Uri为需要查询的数据库的Uri地址,String[] projection为需要返回的列名,String selection为查询条件,String[] selectionArgs为查询条件参数,String sortOrder为是否排序。该方法的返回值为Cursor对象,Cursor对象就类似于一张表格,列数等于查询条件的个数,行数等于数据库中符合查询条件的数据的行数,该对象在使用完之后需要及时关闭。
③.本例中需要查询联系人数据中的raw_contacts表(其Uri为“content://com.android.contacts/raw_contacts”和data表(其Uri为“content://com.android.contacts/data”)。在raw_contacts表中查询列名为“contact_id”的列,该列保存了所有联系人的id。然后通过while循环判断查询出的Cursor对象是否还有下一个,如有则通过getString(int columnIndex)方法获取。由于查询条件只有一个,所以该Cursor对象只有一列,因此getString方法中的参数只能为0,注意参数是指列的角标。
④根据查出的每一个id判断其是否为空,不为空则再通过内容解析器的query方法查询data表中,需要查询的列名为“data1”和“mimetype”,查询条件和参数为contact_id和其值。再通过while循环判断查询出的Cursor对象时候还有下一个,如有则通过getString(int columnIndex)方法获取该Cursor对象里面的数据,其中第一列是data1数据,第二列是mimetype数据。
⑤.根据mimetype数据的值通过equal方法判断所获取的数据是联系人姓名还是电话号码,如果其值为“vnd.android.cursor.item/name”,则获得的数据data1为联系人姓名,如果其值为“vnd.android.cursor.item/phone_v2”,则获得数据data1为联系人电话。
⑥.在新建方法getContactInfo()中新建一个List<Map<String, String>> 的List对象,用于存储取出的所有联系人信息,在第四步中通过if语句判断id不为空后新建Map<String, String>对象,用于存储一个联系人的“name”和“phone”信息(注意,由于List对象和Map对象均为接口类型,因此新建时采用其子类)。然后再第五步中判断数据为联系人姓名还是电话后将其放入Map对象中。
⑦.一个联系人信息放入一个Map对象后,通过add方法将该Map对象放入联系人List对象中,最后返回List对象。
新建获取手机联系人信息的方法(名为getContactInfo())代码:
1 private List<Map<String, String>> getContactInfo() { 2 //获取内容解析器 3 ContentResolver resolver = getContentResolver(); 4 List<Map<String, String>> listContacts = new ArrayList<Map<String,String>>(); 5 //获取手机联系人数据库相关表的Uri 6 Uri uri = Uri.parse("content://com.android.contacts/raw_contacts"); 7 Uri uriData = Uri.parse("content://com.android.contacts/data"); 8 //查询数据表中的相关数据 9 Cursor cursor = resolver.query(uri, new String[] { "contact_id" }, 10 null, null, null); 11 while (cursor.moveToNext()) { 12 String contact_id = cursor.getString(0); 13 if (contact_id != null) { 14 //具体的某一个联系人 15 Map<String,String> mapContact = new HashMap<String, String>(); 16 Cursor dataCursor = resolver.query(uriData, new String[] { 17 "data1", "mimetype" }, "contact_id=?", 18 new String[] { contact_id }, null); 19 while(dataCursor.moveToNext()){ 20 String data1 = dataCursor.getString(0); 21 String mimetype = dataCursor.getString(1); 22 if("vnd.android.cursor.item/name".equals(mimetype)){ 23 //联系人姓名 24 mapContact.put("name", data1); 25 }else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){ 26 //联系人的电话号码 27 mapContact.put("phone", data1); 28 } 29 } 30 //将每个联系人放入List对象中 31 listContacts.add(mapContact); 32 //关闭Cursor对象 33 dataCursor.close(); 34 } 35 } 36 //关闭Cursor对象 37 cursor.close(); 38 return listContacts; 39 }
4、在主方法中通过setAdapter(ListAdapter adapter)方法为主布局文件加载数据和单条数据显示的样式。
①.在layout文件夹下新建一个XML文件用于制作单条数据显示的样式。文本显示格式、大小、排列方式等均可自定义。
单条数据显示样式的XML文件代码:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" > 6 7 <TextView 8 android:id="@+id/contact_item_name" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:text="姓名" 12 android:textSize="22sp"/> 13 14 <TextView 15 android:id="@+id/contact_item_phone" 16 android:layout_width="match_parent" 17 android:layout_height="wrap_content" 18 android:text="电话号码" /> 19 20 </LinearLayout>
②.由于ListAdapter对象是接口,所以新建其子类SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)传入,该方法中第一个参数为上下文(这是this),第二个参数为需要显示的数据(即联系人的List对象),第三个参数为单条数据想要显示的样式的id(即contact_item_view的id),第四个参数和第五个参数分别表示要显示的数据中的某一个数据与样式中要显示位置的对应关系(均以数组的形式对应)。