实现对手机联系人列表进行读写操作,并用RecyclerView收缩展开方式展现
在之前做的类微信界面上加了显示手机联系人,姓名,电话,邮箱三项信息的功能,同时可以添加联系人同步到手机联系人记录中,添加完下拉刷新显示。
在Android中,如果想把A应用的数据库增加一个共享方式,就为A应用写一个ContentProvider方法,标识B应用要访问的数据。然后通过ContentResolver的增删改查方法实现对数据的共享操作。而读写手机联系人的ContentResolver方法直接调用即可。
获取数据存到自定义数据类型里的方法
public void showlist(){
dataBeanList = new ArrayList<>();
Cursor cursor = getActivity().getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
null,null,null,null);
while(cursor.moveToNext()){
String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
dataBean = new DataBean();
dataBean.setID(contactId);
dataBean.setType(0);
dataBean.setChildBean(dataBean);
dataBean.setParentLeftTxt("Name:"+name);
Cursor phones = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"="+contactId,null,null);
while(phones.moveToNext()){
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
dataBean.setChildLeftTxt("MobilePhone:"+phoneNumber);
}
phones.close();
Cursor emails = getActivity().getContentResolver().query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
null, ContactsContract.CommonDataKinds.Email
.CONTACT_ID + " = " + contactId, null, null);
while (emails.moveToNext())
{
// 获取查询结果中E-mail地址列中数据
String emailAddress = emails.getString(emails
.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
dataBean.setChildRightTxt("Email:"+emailAddress);
}
emails.close();
dataBeanList.add(dataBean);
}
cursor.close();
}
相比较之前写的RecyclerView收缩展开静态数据的方式,这次展现的数据是动态的。所以新建了个数据类,用于对手机联系人姓名,号码,邮箱的获取/赋值。由于数据是展开,收缩的形式,便为一级列表和二级列表各写了相应的ViewHolder,两者继承相同的父类。
添加数据功能的思路,在点击添加按钮后出现一个弹框,用EditText接收输入的信息。
final View view1 = getLayoutInflater().inflate(R.layout.addcontact, null);
new AlertDialog.Builder(MainActivity.this).setTitle("添加手机联系人信息").setView(view1).setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
et_name = (EditText)view1.findViewById(R.id.et_name);
et_phone = (EditText)view1.findViewById(R.id.et_phone);
et_email=(EditText)view1.findViewById(R.id.et_email);
String name = et_name.getText().toString();
final String phone = et_phone.getText().toString();
final String email = et_email.getText().toString();
// 创建一个空的ContentValues
ContentValues values = new ContentValues();
// 向RawContacts.CONTENT_URI执行一个空值插入
// 目的是获取系统返回的rawContactId
Uri rawContactUri = getContentResolver().insert(ContactsContract.RawContacts.CONTENT_URI, values);
long rawContactId = ContentUris.parseId(rawContactUri);
values.clear();
values.put(Data.RAW_CONTACT_ID, rawContactId);
// 设置内容类型
values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
// 设置联系人名字
values.put(StructuredName.GIVEN_NAME, name);
// 向联系人URI添加联系人名字
getContentResolver().insert(ContactsContract
.Data.CONTENT_URI, values);
values.clear();
values.put(Data.RAW_CONTACT_ID, rawContactId);
values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
// 设置联系人的电话号码
values.put(Phone.NUMBER, phone);
// 设置电话类型
values.put(Phone.TYPE, Phone.TYPE_MOBILE);
// 向联系人电话号码URI添加电话号码
getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
values.clear();
values.put(Data.RAW_CONTACT_ID, rawContactId);
values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
// 设置联系人的E-mail地址
values.put(Email.DATA, email);
// 设置该电子邮件的类型
values.put(Email.TYPE, Email.TYPE_WORK);
// 向联系人E-mail URI添加E-mail数据
getContentResolver().insert(ContactsContract.Data.CONTENT_URI, values);
}
}).show();
最初没有写刷新功能,添加完后得重新进入应用才能显示,于是参照刷新布局控件
SwipeRefreshLayout的使用方法,加了个下拉刷新的功能。
布局文件
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/srl"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/rcv_expandcollapse"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:overScrollMode="never"
android:scrollbars="none"/>
</android.support.v4.widget.SwipeRefreshLayout>
刷新部分的实现
private SwipeRefreshLayout msrl;
msrl = view.findViewById(R.id.srl);
msrl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
showlist();
setData();
msrl.setRefreshing(false);
}
},1200);
}
});
实现效果如下
这次遇到了大大小小很多错误,其中最令人深刻的是下面这个空指针异常的错误。
错误部分的代码如下
case R.id.id_add_contact:
final View view1 = getLayoutInflater().inflate(R.layout.addcontact, null);
new AlertDialog.Builder(MainActivity.this).setTitle("添加手机联系人信息").setView(view1).setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
et_name = (EditText)view1.findViewById(R.id.et_name);
et_phone = (EditText)view1.findViewById(R.id.et_phone);
et_email=(EditText)view1.findViewById(R.id.et_email);
最后找到了原因是我实例化EditText时,没有加view1,导致我在处理这个错误上花了很多时间。最后查找了关于findViewById的解释,才明白,findViewById默认上下文是在Activity的主布局中,在子布局,如弹窗Dialog中,要用view.findViewById方法才行。