SQLite数据库操作之读取手机联系人

1 ContentProvider组件

1.1 简介

Android系统自带了一些应用,对应的数据库分别存储了联系人信息、音乐文件和短信息等。出于安全性考虑,不允许用户编程直接操作上述数据库(如删除数据表、修改表结构等),而是提供了相应的内容提供者组件,通过相应的Uri来实现信息检索——ContentProvider。
ContentProvider是实现应用程序间数据共享最标准的方式,是Android四大组件中的一个。应用程序通过ContentResolver对象访问ContentProvider中的数据,该对象提供了持久层数据的CRUD方法。

1.2 一些应用的Uri

手机联系人:ContactsContract.Contacts.CONTENT_URI;
音频: MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
短信:Uri.parse(“content://sms”);
图片:MediaStore.Images.Media.EXTERNAL_CONTENT_UR;
视频:MediaStore.Video.Media.EXTERNAL_CONTENT_URI

2 实践

2.1 要求:

读取手机联系人中的信息,并在RecyclerView中显示出来。

2.2 手机联系人信息

手机联系人信息存储位置:
手机系统目录data/data下的包com.android.providers.contacts里,存放手机联系人数据库contacts2.db。

手机联系人信息存储结构
数据库contacts2.db里包含表raw_contacts,联系人id存放在字段contact_id里。
在这里插入图片描述
表data存放了联系人的具体信息。
在这里插入图片描述
表contacts存放了联系人的其它信息。
在这里插入图片描述

2.3 实际操作

(1)在Fragment对应的布局文件中添加RecyclerView组件以及相应的.xml文件
主布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="@android:color/holo_green_dark"
        android:gravity="center"
        android:text="这是微信联系人界面"
        android:textSize="25sp"
        android:textStyle="bold" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rcv_contacts"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

</LinearLayout>

RecyclerView使用的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">


    <LinearLayout
        android:id="@+id/LLName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tv_Name1"
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:text="姓名"
            android:textColor="@android:color/background_dark"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/tv_Name2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="8dp"
            android:text="TextView"
            android:textColor="@android:color/background_dark"
            android:textSize="18sp" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/LLPhone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/tv_Phone1"
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:text="电话号码"
            android:textColor="@android:color/background_dark"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/tv_Phone2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:text="TextView"
            android:textColor="@android:color/background_dark"
            android:textSize="18sp" />
    </LinearLayout>

</LinearLayout>

(2)编写RecyclerView适配器

public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ContactsViewHolder> {

    private List<ContactsAccount> contactsAccounts;
    private Context mContext;

    public ContactsAdapter(Context context, List<ContactsAccount> contactsAccounts) {
        mContext=context;
        this.contactsAccounts = contactsAccounts;
    }

    @Override
    public ContactsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.tab03_recyclerview_item, parent, false);
        return new ContactsViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ContactsViewHolder holder, int position) {

        holder.tv_Name2.setText(contactsAccounts.get(position).getName());
        holder.tv_Phone2.setText(contactsAccounts.get(position).getPhoneNumber());

    }


    @Override
    public int getItemCount() {
        return contactsAccounts.size();
    }

    class ContactsViewHolder extends RecyclerView.ViewHolder {

        LinearLayout LLName,LLPhone;
        TextView tv_Name1, tv_Name2,tv_Phone1,tv_Phone2;
        public ContactsViewHolder(@NonNull View itemView) {
            super(itemView);

            LLName=itemView.findViewById(R.id.LLName);
            LLPhone=itemView.findViewById(R.id.LLPhone);
            tv_Name1=itemView.findViewById(R.id.tv_Name1);
            tv_Name2=itemView.findViewById(R.id.tv_Name2);
            tv_Phone1=itemView.findViewById(R.id.tv_Phone1);
            tv_Phone2=itemView.findViewById(R.id.tv_Phone2);

        }
    }
}

(3)联系人实体类

public class ContactsAccount {
    private String Name;
    private String PhoneNumber;

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public String getPhoneNumber() {
        return PhoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        PhoneNumber = phoneNumber;
    }
}

(4)在Fragment中编写读取联系人信息和显示代码

public class contactFragment extends Fragment {

    private ContentResolver contentResolver;//=getContext().getContentResolver();
    private View view;
    private RecyclerView recyclerView;
    private List<ContactsAccount> contactsAccountList=new ArrayList<>();
    private ContactsAdapter contactsAdapter;

    public contactFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this.getActivity(),new String[]{Manifest.permission.READ_CONTACTS},1);
        }

        // Inflate the layout for this fragment
        view= inflater.inflate(R.layout.tab03, container, false);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        ImageButton imageButton=(ImageButton)getActivity().findViewById(R.id.btn_contacts_img);
        imageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                fun();
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    }


    public  void fun(){
        recyclerView=(RecyclerView)getActivity().findViewById(R.id.rcv_contacts);

        //获取手机联系人的Uri,相当于提供了一个公共的数据库链接
        Uri uri= ContactsContract.Contacts.CONTENT_URI;//内部类静态成员
        //android.content.Context提供了抽象方法getContentResolver()方法
        //通过内容(数据)解析器使用抽象类android.content.ContentResolver提供了query()等方法
        Cursor cursor=getContext().getContentResolver().query(uri, null, null, null, null);  //得到记录集
        while(cursor.moveToNext()){
            //先获取联系人_id字段的索引号后再获取_id值
            int idFieldIndex=cursor.getColumnIndex("_id");//法一
            //int idFieldIndex=cursor.getColumnIndex(ContactsContract.Contacts._ID);//法二
            int id=cursor.getInt(idFieldIndex);

            //先获取联系人姓名字段的索引号后再获取姓名字段值
            int nameFieldIndex  = cursor.getColumnIndex("display_name");
            //int nameFieldIndex=cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
            String name=cursor.getString(nameFieldIndex);

            int numCountFieldIndex=cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
            int numCount=cursor.getInt(numCountFieldIndex);   //获取联系人的电话号码个数
            String phoneNumber="";
            if(numCount>0){       //联系人有至少一个电话号码
                //在类ContactsContract.CommonDataKinds.Phone中根据id查询相应联系人的所有电话;
                Cursor phonecursor=getContext().getContentResolver().query(
                        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                        null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"=?",
                        new String[]{Integer.toString(id)}, null);
                if(phonecursor.moveToFirst()){     //仅读取第一个电话号码
                    int numFieldIndex=phonecursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
                    phoneNumber=phonecursor.getString(numFieldIndex);
                }
            }

            ContactsAccount contactsAccount=new ContactsAccount();
            contactsAccount.setName(name);
            contactsAccount.setPhoneNumber(phoneNumber);
            contactsAccountList.add(contactsAccount);
        }

        contactsAdapter=new ContactsAdapter(getContext(),contactsAccountList);
        recyclerView.setAdapter(contactsAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
       // recyclerView.setHasFixedSize(true);

    }

}

注意点
(1)ImgButton的点击监听方法不能写在public View onCreateView()方法中,需写在public void onActivityCreated()方法中。
(2)联系人实体类对象必须在循环中创建,否则会覆盖。

ContactsAccount contactsAccount=new ContactsAccount();
contactsAccount.setName(name);
contactsAccount.setPhoneNumber(phoneNumber);
contactsAccountList.add(contactsAccount);

(3) 在Fragment中,使用getContentResolver()方法时需注上下文对象,即getContext()。

Cursor cursor=getContext().getContentResolver().query(uri, null, null, null, null); 

(4)由于该应用需要读取手机联系人信息,需要在清单文件里注册读取联系人权限,代码如下:

<uses-permission android:name="android.permission.READ_CONTACTS"/>
2.4项目结果演示

查询前:
在这里插入图片描述
查询后:
在这里插入图片描述
该项目主要通过getContext().getContentResolver()获取ContentResolver对象,在通过ContentResolver获取ContentProvider提供的数据。最终将查询到的数据显示在RecyclerView上。
项目源码链接

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值