欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

获取通讯录内容,并对其进行增删改操作

程序员文章站 2022-04-20 08:36:36
获取通讯录内容,并对其进行增删改操作案例效果案例效果图思路分析模块分析主界面的功能初始化界面initView()初始化数据动态权限申请获取数据案例效果1.回顾recycler View控件的使用2.实现ContentResolver的相关API3.熟悉安卓系统中通讯录的几个关键表之间的关联案例效果图思路分析1.主界面由一个recyclerView控件和一个Button控件构成。2.长按recyclerView控件会弹出一个编辑菜单。3.用ContentResolver来获取通信录中的数据...

案例效果

1.回顾recycler View控件的使用
2.实现ContentResolver的相关API
3.熟悉安卓系统中通讯录的几个关键表之间的关联

案例效果图

获取通讯录内容,并对其进行增删改操作

思路分析

1.主界面由一个recyclerView控件和一个Button控件构成。
2.长按recyclerView控件会弹出一个编辑菜单。
3.用ContentResolver来获取通信录中的数据。

模块分析

主界面的功能

1.初始化界面
2.获取数据
注意:要动态的申请权限
由于每次回到该页面,都会执行onResume()方法,故将数据的初始化和获取,写在这个函数里,就可以实时地更新数据。

初始化界面initView()

实现长按item弹出菜单,要对recycler View对象进行注册。
registerForContextMenu(rvContract);

private void initView() {
    rvContract = (RecyclerView) findViewById(R.id.rvContract);
    btn_add = (Button) findViewById(R.id.btn_add);
    //传入线性布局
    rvContract.setLayoutManager(new LinearLayoutManager(this));
    mList = new ArrayList<>();
    mAdapter = new ContactAdapter(this, mList);
    rvContract.setAdapter(mAdapter);
    //实现长按item弹出菜单
    registerForContextMenu(rvContract);
    btn_add.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(MainActivity.this, AddOrModifyActivity.class);
            intent.putExtra(IS_ADD_KEY, true);
            startActivity(intent);
        }
    });

}

初始化数据

动态权限申请

 int readContacts = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS);
    int writeContacts = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CONTACTS);
    if (readContacts == PackageManager.PERMISSION_GRANTED && writeContacts ==
            PackageManager.PERMISSION_GRANTED) {
        //开始获取数据
        getData();
    } else {
        ActivityCompat.requestPermissions(this, contactPermissions, CONTACT_REQUEST_CODE);
    }
}

获取权限后回调

/**
 * 用户回复后,都会回调这个函数
 *
 * @param requestCode
 * @param permissions
 * @param grantResults 授权的结果保存在此
 */
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case CONTACT_REQUEST_CODE:
            int length = contactPermissions.length;
            boolean flag = true;
            for (int i = 0; i < length; i++) {
                //PERMISSION_DENIED为被拒绝的权限集
                if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                    flag = false;
                    break;
                }
                if (flag) {
                    getData();
                }
            }
    }
}

获取数据

/**
 * ContactsContract.RawContacts.CONTENT_URI是指原始表的URI
 */
@RequiresApi(api = Build.VERSION_CODES.O)
private void getData() {
    mList.clear();//清空之前的查询结果
    Cursor cursor = resolver.query(ContactsContract.RawContacts.CONTENT_URI, null, null,
            null);
    while (cursor.moveToNext()) {
        //新建一个Bean来存储数据
        ContactBean bean = new ContactBean();
        int id = cursor.getInt(cursor.getColumnIndex(ContactsContract.RawContacts._ID));
        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
        //一个用户的手机号可能有多个,故手机号是一个集合。,取第一个手机号
        String phone = null;
        Cursor phoneCursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                null, ContactsContract.Data.RAW_CONTACT_ID + "=?", new String[]{
                        String.valueOf(id)}, null);
        if (phoneCursor.moveToFirst()) {
            phone = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.
                    CommonDataKinds.Phone.NUMBER));
        }
        phoneCursor.close();
        bean.setId(id);
        bean.setName(name);
        bean.setPhone(phone);
        mList.add(bean);
    }
    cursor.close();
    mAdapter.notifyDataSetChanged();//recyclerView里的数据刷新。
}

添加或者修改界面

1.获取EditView上的数据
2.新建一个ContentValue对象,将数据封装在里面
3.调用ContentResolver进行添加和修改操作
对于安卓如何封装和解析通讯录数据表的内容
参考使用ContentResolver来对通讯录进行增删改查

数据初始化

private void initData() {
    Intent intent = getIntent();
    is_add = intent.getBooleanExtra(IS_ADD_KEY,true);
    resolver = getContentResolver();
    bean = intent.getParcelableExtra(BEAN_KEY);//如果之前没有传入,就是null.
    if (bean !=null){
        //将数据显示出来
       etName.setText(bean.getName());
       etPhone.setText(bean.getPhone());
    }
}

根据Boolean值判断执行何种操作

is_add是是否为添加事件的判断。

public void onViewClicked() {
    name = etName.getText().toString();
    phone = etPhone.getText().toString();
    if (TextUtils.isEmpty(name)){
        toastShow("请输入联系人姓名");
    }else if (TextUtils.isEmpty(phone)){
        toastShow("请输入联系人电话");
    }else {
        if (is_add){
            insertContact();
        }else {
            updateContact();
        }
    }

添加数据

private void insertContact() {
    /**
     * 首先向row_contact表中插入一条既然,目的是为了获取raw_contact_id字段
     */
    ContentValues values = new ContentValues();
    Uri rawContactUri = resolver.insert(ContactsContract.RawContacts.CONTENT_URI,values);
    //ContentUris一个uri相关的工具类
    long rawContactId = ContentUris.parseId(rawContactUri);//通过uri获取id
    /**
     * 在row_contact中的一条数据是对应DAta表中的两条数据,古要单独插入。
     * 插入姓名
     */
    values.clear();
    values.put(ContactsContract.Data.RAW_CONTACT_ID,rawContactId);
    //MIMETYPE是指文件类型,eg.html...
    values.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.
            StructuredName.CONTENT_ITEM_TYPE);
    values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,name);
    Uri nameUri = resolver.insert(ContactsContract.Data.CONTENT_URI, values);
    /**
     * 插入手机号
     */
    values.clear();
    values.put(ContactsContract.Data.RAW_CONTACT_ID,rawContactId);
    //MIMETYPE是指文件类型,eg.html...
    values.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.
           Phone.CONTENT_ITEM_TYPE);
    values.put(ContactsContract.CommonDataKinds.Phone.NUMBER,phone);
    Uri phoneUri = resolver.insert(ContactsContract.Data.CONTENT_URI, values);

    if (nameUri !=null && phoneUri!= null){
        toastShow("保存成功");
    }else {
        toastShow("保存失败");
    }
    finish();//结束该界面
}

三级标题

private void updateContact() {
    ContentValues values = new ContentValues();
    values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name);
    values.put(ContactsContract.CommonDataKinds.Phone.NUMBER,phone);
    Log.d("updateContact", "values已经产生");
    int result = resolver.update(ContactsContract.Data.CONTENT_URI, values,
            ContactsContract.Data.RAW_CONTACT_ID +"=?",new String[]{
        String.valueOf(bean.getId())});
    if (result > 0){
        toastShow("修改成功");
    }else {
        toastShow("修改失败");
    }
    finish();//关闭当前页面
}

全部代码

mainActivity

package com.example.contentproviderdemo.activity;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.example.contentproviderdemo.R;

import Bean.ContactBean;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class AddOrModifyActivity extends AppCompatActivity {

    @BindView(R.id.et_name)
    EditText etName;
    @BindView(R.id.et_phone)
    EditText etPhone;
    @BindView(R.id.btn_save)
    Button btnSave;

    private static final String IS_ADD_KEY = "IS_ADD_KEY";
    private static final String BEAN_KEY= "BEAN_KEY";

    private boolean is_add;//null
    private ContentResolver resolver;//null
    private String name;//null
    private String phone;//null
    private ContactBean bean;//null


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_or_modify);
        ButterKnife.bind(this);
        initData();

    }

    private void initData() {
        Intent intent = getIntent();
        is_add = intent.getBooleanExtra(IS_ADD_KEY,true);
        resolver = getContentResolver();
        bean = intent.getParcelableExtra(BEAN_KEY);//如果之前没有传入,就是null.
        if (bean !=null){
            //将数据显示出来
           etName.setText(bean.getName());
           etPhone.setText(bean.getPhone());
        }
    }

    @OnClick(R.id.btn_save)
    public void onViewClicked() {
        name = etName.getText().toString();
        phone = etPhone.getText().toString();
        if (TextUtils.isEmpty(name)){
            toastShow("请输入联系人姓名");
        }else if (TextUtils.isEmpty(phone)){
            toastShow("请输入联系人电话");
        }else {
            if (is_add){
                insertContact();
            }else {
                updateContact();
            }
        }


    }

    private void updateContact() {
        ContentValues values = new ContentValues();
        values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name);
        values.put(ContactsContract.CommonDataKinds.Phone.NUMBER,phone);
        Log.d("updateContact", "values已经产生");
        int result = resolver.update(ContactsContract.Data.CONTENT_URI, values,
                ContactsContract.Data.RAW_CONTACT_ID +"=?",new String[]{
            String.valueOf(bean.getId())});
        if (result > 0){
            toastShow("修改成功");
        }else {
            toastShow("修改失败");
        }
        finish();//关闭当前页面
    }

    private void insertContact() {
        /**
         * 首先向row_contact表中插入一条既然,目的是为了获取raw_contact_id字段
         */
        ContentValues values = new ContentValues();
        Uri rawContactUri = resolver.insert(ContactsContract.RawContacts.CONTENT_URI,values);
        //ContentUris一个uri相关的工具类
        long rawContactId = ContentUris.parseId(rawContactUri);//通过uri获取id
        /**
         * 在row_contact中的一条数据是对应DAta表中的两条数据,古要单独插入。
         * 插入姓名
         */
        values.clear();
        values.put(ContactsContract.Data.RAW_CONTACT_ID,rawContactId);
        //MIMETYPE是指文件类型,eg.html...
        values.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.
                StructuredName.CONTENT_ITEM_TYPE);
        values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,name);
        Uri nameUri = resolver.insert(ContactsContract.Data.CONTENT_URI, values);
        /**
         * 插入手机号
         */
        values.clear();
        values.put(ContactsContract.Data.RAW_CONTACT_ID,rawContactId);
        //MIMETYPE是指文件类型,eg.html...
        values.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.
               Phone.CONTENT_ITEM_TYPE);
        values.put(ContactsContract.CommonDataKinds.Phone.NUMBER,phone);
        Uri phoneUri = resolver.insert(ContactsContract.Data.CONTENT_URI, values);

        if (nameUri !=null && phoneUri!= null){
            toastShow("保存成功");
        }else {
            toastShow("保存失败");
        }
        finish();//结束该界面
    }

    private void toastShow(String s) {
        Toast.makeText(this,s,Toast.LENGTH_SHORT).show();
    }
}

recyclerView的适配器代码
其中viewHolder要手动实现监听内容菜单的接口,

static class ContractViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener

并且在类的构造器中进行设置。

itemView.setOnCreateContextMenuListener(this);

全部代码

package com.example.contentproviderdemo;

import android.content.Context;
import android.content.Intent;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.example.contentproviderdemo.activity.MainActivity;

import java.util.List;

import Bean.ContactBean;

/**
 * @ 功能适配器中必须要有实体类,也是bean
 * 1.数据的绑定,2.创建viewHolder--布局加载器--上下文对象
 * Ctreate by barry on 2020/9/20.
 */
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContractViewHolder> {
    private Context mContext;//null
    private List<ContactBean> mList;//null
    private LayoutInflater mInflater;//null

    private static final String POSITION_KEY ="POSITION_KEY";

    public ContactAdapter(Context mContext, List<ContactBean> mList) {
        this.mContext = mContext;
        this.mList = mList;
        mInflater = LayoutInflater.from(mContext);
    }

    /**
     * 创建ViewHolder实例,并将item布局加载进入
     * @param parent
     * @param viewType
     * @return
     */
    @NonNull
    @Override
    public ContractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //加载item布局
        View view = mInflater.inflate(R.layout.recyclerview_item_contact,parent,false);
        ContractViewHolder viewHolder = new ContractViewHolder(view);
        return viewHolder;
    }

    /**
     * 对vieholder对象进行数据赋值
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(@NonNull ContractViewHolder holder, int position) {
        ContactBean contact = mList.get(position);
        holder.tvName.setText(contact.getName());
        holder.tvPhone.setText(contact.getPhone());

    }

    /**
     * 统计item个数
     * @return
     */
    @Override
    public int getItemCount() {
        return mList.size();
    }

    static class ContractViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener{
        private TextView tvName;//null
        private TextView tvPhone;//null

        public ContractViewHolder(@NonNull View itemView) {
            super(itemView);
            tvName = (TextView)itemView.findViewById(R.id.tv_name);
            tvPhone = (TextView)itemView.findViewById(R.id.tv_phone);
            //由于recycleView没有实现长按弹出菜单的接口,要在ViewHolder中自己实现该接口
            //setOnCreateContextMenuListener(OnCreateContextMenuListener l)
            // 由于ContractViewHolder已经实现该接口,故直接传入this
            itemView.setOnCreateContextMenuListener(this);

        }
        //创建响应的菜单

        @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
            //获取当前所按的item的下标,回传到MainActivity*onContextItemSelected使用。
            int position = getAdapterPosition();
            Intent intent = new Intent();//这里不需要使用intent,来跳转
            intent.putExtra(POSITION_KEY,position);

            menu.setHeaderTitle("编剧");
            //菜单的选项时通过add来直接添加,通过setIntent(),让每一个MenuItem自带了一个intent
            menu.add(0,0,0,"修改").setIntent(intent);
            menu.add(0,1,0,"删除").setIntent(intent);

        }
    }
}

实体类的代码—为了在活动之间进行传输,要实现序列化

package Bean;

import android.os.Parcel;
import android.os.Parcelable;

/**由于要在不同的活动之间进行传递,该类必须实现序列化1.seriable 2.Parcelable
 * @ 功能
 * Ctreate by barry on 2020/9/22.
 */
public class ContactBean implements Parcelable {
    private int id;
    private String name;
    private String phone;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.id);
        dest.writeString(this.name);
        dest.writeString(this.phone);
    }

    public ContactBean() {
    }

    protected ContactBean(Parcel in) {
        this.id = in.readInt();
        this.name = in.readString();
        this.phone = in.readString();
    }

    public static final Parcelable.Creator<ContactBean> CREATOR = new Parcelable.Creator<ContactBean>() {
        @Override
        public ContactBean createFromParcel(Parcel source) {
            return new ContactBean(source);
        }

        @Override
        public ContactBean[] newArray(int size) {
            return new ContactBean[size];
        }
    };
}

添加修改界面的代码

package com.example.contentproviderdemo.activity;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.example.contentproviderdemo.R;

import Bean.ContactBean;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class AddOrModifyActivity extends AppCompatActivity {

    @BindView(R.id.et_name)
    EditText etName;
    @BindView(R.id.et_phone)
    EditText etPhone;
    @BindView(R.id.btn_save)
    Button btnSave;

    private static final String IS_ADD_KEY = "IS_ADD_KEY";
    private static final String BEAN_KEY= "BEAN_KEY";

    private boolean is_add;//null
    private ContentResolver resolver;//null
    private String name;//null
    private String phone;//null
    private ContactBean bean;//null


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_or_modify);
        ButterKnife.bind(this);
        initData();

    }

    private void initData() {
        Intent intent = getIntent();
        is_add = intent.getBooleanExtra(IS_ADD_KEY,true);
        resolver = getContentResolver();
        bean = intent.getParcelableExtra(BEAN_KEY);//如果之前没有传入,就是null.
        if (bean !=null){
            //将数据显示出来
           etName.setText(bean.getName());
           etPhone.setText(bean.getPhone());
        }
    }

    @OnClick(R.id.btn_save)
    public void onViewClicked() {
        name = etName.getText().toString();
        phone = etPhone.getText().toString();
        if (TextUtils.isEmpty(name)){
            toastShow("请输入联系人姓名");
        }else if (TextUtils.isEmpty(phone)){
            toastShow("请输入联系人电话");
        }else {
            if (is_add){
                insertContact();
            }else {
                updateContact();
            }
        }


    }

    private void updateContact() {
        ContentValues values = new ContentValues();
        values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, name);
        values.put(ContactsContract.CommonDataKinds.Phone.NUMBER,phone);
        Log.d("updateContact", "values已经产生");
        int result = resolver.update(ContactsContract.Data.CONTENT_URI, values,
                ContactsContract.Data.RAW_CONTACT_ID +"=?",new String[]{
            String.valueOf(bean.getId())});
        if (result > 0){
            toastShow("修改成功");
        }else {
            toastShow("修改失败");
        }
        finish();//关闭当前页面
    }

    private void insertContact() {
        /**
         * 首先向row_contact表中插入一条既然,目的是为了获取raw_contact_id字段
         */
        ContentValues values = new ContentValues();
        Uri rawContactUri = resolver.insert(ContactsContract.RawContacts.CONTENT_URI,values);
        //ContentUris一个uri相关的工具类
        long rawContactId = ContentUris.parseId(rawContactUri);//通过uri获取id
        /**
         * 在row_contact中的一条数据是对应DAta表中的两条数据,古要单独插入。
         * 插入姓名
         */
        values.clear();
        values.put(ContactsContract.Data.RAW_CONTACT_ID,rawContactId);
        //MIMETYPE是指文件类型,eg.html...
        values.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.
                StructuredName.CONTENT_ITEM_TYPE);
        values.put(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,name);
        Uri nameUri = resolver.insert(ContactsContract.Data.CONTENT_URI, values);
        /**
         * 插入手机号
         */
        values.clear();
        values.put(ContactsContract.Data.RAW_CONTACT_ID,rawContactId);
        //MIMETYPE是指文件类型,eg.html...
        values.put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.
               Phone.CONTENT_ITEM_TYPE);
        values.put(ContactsContract.CommonDataKinds.Phone.NUMBER,phone);
        Uri phoneUri = resolver.insert(ContactsContract.Data.CONTENT_URI, values);

        if (nameUri !=null && phoneUri!= null){
            toastShow("保存成功");
        }else {
            toastShow("保存失败");
        }
        finish();//结束该界面
    }

    private void toastShow(String s) {
        Toast.makeText(this,s,Toast.LENGTH_SHORT).show();
    }
}

清单文件–两个权限的申请


<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

本文地址:https://blog.csdn.net/Barryjacket/article/details/108821453

相关标签: 移动开发