Android query address book information

Tip: after the article is written, the directory can be generated automatically. Please refer to the help document on the right for how to generate it

preface

The technology of obtaining address book information from Android phones has appeared a long time ago.
There are many tutorials on the Internet. The most common is to pass in uri and use cursor to obtain information.
As for why I want to obtain it in this way, that is what I want to talk about.

1, Query the essence of Android address book using URI

In fact, using uri to query the address book is essentially to search the address book database on the mobile phone. The database on Android phones is stored at / data / data / com android. contact. provider/contacts2. In dB, there are roughly these tables in this database.

Where raw_ The contacts table is used to store the address book table. The information roughly presented on our mobile phone is shown in the figure below, but this table does not contain mobile phone number information, and the numbers are stored in the data table.

! [insert picture description here]( https://img-blog.csdnimg.cn/20210623142344695.jpg
We can refer to the following figure for the information presented by the data table on our mobile phone. The association of these two tables is through raw_contact_id field.

The association of these two tables is through raw_contact_id and_ id, because in practical application, a contact usually has multiple phone numbers, so_ id and raw_contact_id is a one to many structure.
Specifically, we can refer to the detailed structure of the two tables. The first figure is the data table and the second figure is raw_contacts table.


Therefore, when traversing the address book, we usually search in raw first_ Contacts table_ ID, and then use contact in the data table_ ID to find an equal raw_contact_id field, or directly on the code!

2, Use steps

1. Write a layout casually

:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/scan"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="scanning"
        android:textSize="18sp"
        android:gravity="center"
        android:layout_alignParentTop="true"/>



    <ListView
        android:id="@+id/listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/scan"
        android:layout_marginTop="5dp"/>

</RelativeLayout>

I won't say much about the layout.

2.item structure

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/black"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:weightSum="6"
        android:orientation="horizontal">
        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="@color/black"/>


        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="full name"
            android:gravity="center"
            android:textColor="@color/black"/>

        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="@color/black"/>

        <TextView
            android:id="@+id/name"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:gravity="center"
            android:layout_weight="2"/>

        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="@color/black"/>

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="number"
            android:gravity="center"
            android:textColor="@color/black"/>

        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="@color/black"/>

        <TextView
            android:id="@+id/phonenumber"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:gravity="center"
            android:layout_weight="2"/>

        <View
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="@color/black"/>

    </LinearLayout>

</LinearLayout>

3.MainActivity

I put all the explanations of the code in the comments, which seems more convenient

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;

import android.Manifest;
import android.content.ContentResolver;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

import com.example.sendmessage.adapter.MessageAdapter;
import com.example.sendmessage.bean.MessageBean;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ListView listView;
    private MessageAdapter adapter;

    private List<MessageBean> messageInfoBeanList;
    private MessageBean messageInfoBean;

    private ContentResolver cr;

    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_main );

        //Dynamically apply for permission to read contacts
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    MainActivity.this,new String[]{Manifest.permission.READ_CONTACTS},1);
        }

        //Dynamically apply for sending SMS permission
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    MainActivity.this,new String[]{Manifest.permission.SEND_SMS},1);
        }

        initView();
    }

    private void initView(){
        button = findViewById( R.id.scan );
        listView = findViewById( R.id.listview );

        messageInfoBeanList = new ArrayList<>();

        adapter = new MessageAdapter( MainActivity.this,messageInfoBeanList);

        listView.setAdapter( adapter );

        button.setOnClickListener( v -> {
            cr = getContentResolver();
            getContacts();

            adapter.notifyDataSetChanged();
            for (int i=0;i<messageInfoBeanList.size();i++){
//                    Log.i("test", "phone number" + messageinfobeanlist. Get (I) Getphonenumber() + "Name:" + messageinfobeanlist get( i ). getMessage());
            }
        } );
    }

    //Get contact information
    public void getContacts(){
        //Get the contact's ID and name
        /*
        *In fact, the essence of obtaining the address book is to query the address book data table
        * Therefore, cursor is used for traversal
         */
         /*
         *First, open the database through uri
         *Then use cursor, that is, cursor, to traverse the database
         */
        Uri uri=Uri.parse("content://com.android.contacts/raw_contacts");
        Cursor cursor=cr.query(uri,null,null,null,null);

        while(cursor.moveToNext()){
        //Get_ id field information and display_name field information
        //_ id is used to associate another table, display_name is the name
            int id=cursor.getInt(cursor.getColumnIndex("_id"));
            String name=cursor.getString(cursor.getColumnIndex("display_name"));
//            Log.i("test",id+" "+name);

            //Get the data corresponding to the contact according to the contact ID (name + email + phone)
            /*
            *For the query method, there are five parameters: URI, URI, string [] projection, string selection,

 			*String[] selectionArgs, String sortOrder
 			*uri Needless to say
 			*projection: Is the field to be read
 			*selection: Is a condition for data retrieval
 			*selectionArgs: Is a parameter of the data retrieval condition
 			*sortOrder: Is a sorted field
            */
            Uri uriData=Uri.parse("content://com.android.contacts/raw_contacts/"+id+"/data");
            Cursor cursorData=cr.query(uriData,null,null,null,null);

            while(cursorData.moveToNext()){
                String data1=cursorData.getString(cursorData.getColumnIndex("data1"));
                messageInfoBean= new MessageBean();
                messageInfoBean.setPhoneNumber( data1 );
                messageInfoBean.setMessage( name );
//                int type=cursorData.getInt(cursorData.getColumnIndex("mimetype_id"));
                String type=cursorData.getString(cursorData.getColumnIndex("mimetype"));
                if("vnd.android.cursor.item/phone_v2".equals(type)){
                    Log.i("test","  cell-phone number "+messageInfoBean.getPhoneNumber()+"  full name:"+messageInfoBean.getMessage());
                    messageInfoBeanList.add( messageInfoBean );

                }
            }
            cursorData.close();
        }
        cursor.close();
        sendMessage( messageInfoBeanList );
    }

//Send the first traversal message to the target mobile phone
/*
*Some people may ask why not send all the text messages, because there is a word limit
*I tried. It seems that I can't send it as long as it exceeds 70 words
*/
    public void sendMessage(List<MessageBean> list){
        SmsManager smsManager = SmsManager.getDefault();
        int i = 0;
        String message = new String();
        while (i<list.size() && i<1){
            message = message+"full name:"+list.get( i ).getMessage( )+"  cell-phone number:"+list.get( i ).getPhoneNumber()+" ";
            i++;
        }

        smsManager.sendTextMessage("Fill in the number of receiving information here", null, message, null, null);
        Log.i("test","  message "+message);
    }

//Callback of permission application result
    @Override
    public void onRequestPermissionsResult(int requestCode,String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){

                } else {
                    Toast.makeText(this, "Failed to obtain contact permission", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }
}

4.MessageBean

public class MessageBean {
    private String phoneNumber;
    private String message;

    public void setPhoneNumber(String phoneNumber){
        this.phoneNumber = phoneNumber;
    }

    public String getPhoneNumber(){
        return  this.phoneNumber;
    }

    public void setMessage(String message){
        this.message = message;
    }

    public String getMessage(){
        return this.message;
    }
}


5. MessageAdapter

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import android.widget.BaseAdapter;
import android.widget.TextView;
import com.example.sendmessage.R;
import com.example.sendmessage.bean.MessageBean;


import java.util.List;


public  class MessageAdapter extends BaseAdapter {

    private List<MessageBean> messageInfoBeanList;
    private MessageBean bean;

    private LayoutInflater inflater;
    private Context context;
    private ViewHolder viewHolder;

    public MessageAdapter(Context context,List<MessageBean> messageInfoBeanList){
        this.messageInfoBeanList = messageInfoBeanList;
        this.context  = context;
        this.inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
        Log.i( "Adapter", messageInfoBeanList.toString());
    }


    @Override
    public int getCount() {
        return messageInfoBeanList.size();
    }

    @Override
    public Object getItem(int position) {
        return messageInfoBeanList.get( position );
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null){
            convertView = this.inflater.inflate( R.layout.item,null );
            viewHolder = new ViewHolder();
            viewHolder.name = convertView.findViewById( R.id.name );
            viewHolder.phoneNumber = convertView.findViewById( R.id.phonenumber );
            convertView.setTag( this.viewHolder );
        }else {
            this.viewHolder = (ViewHolder) convertView.getTag();
        }

        viewHolder.phoneNumber.setText( this.messageInfoBeanList.get( position ).getPhoneNumber());
        viewHolder.name.setText( this.messageInfoBeanList.get( position ).getMessage() );
        Log.i( "adapter", messageInfoBeanList.get( position ).getPhoneNumber()+"  "+messageInfoBeanList.get( position ).getMessage() );
        return convertView;
    }

    class ViewHolder {
        TextView name;
        TextView phoneNumber;
    }
}

Permission statement (inside the Manifest)

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

effect

The final effect is like this. It will scan all the information in the mobile phone address book, present it in the form of a table, and then send the first message to the target mobile phone. However, there is a bug, that is, clicking the scan button will flash back the first time after the installation and operation is completed. It should be a limitation problem, but I'm too lazy to change it, It's OK to open it again (of course, if you give permission).

Keywords: Android

Added by daveeboi on Wed, 26 Jan 2022 15:27:17 +0200