ContentProvider “读取联系人”

ContentProvider主要用于不同应用程序之间共享数据,比如联系人、短信、媒体库等都实现了跨应用数据共享功能。
ContentProvider在提供数据共享的同时还能保证被访问数据的安全性。

代码演示“读取联系人”

  1. 创建一个项目ContentProviderSample

  2. 新建 Activity,名为 ContactsActivity

  3. 配置 AndroidManifest.xml,添加读取联系人权限
    <uses-permission android:name="android.permission.READ_CONTACTS" />

  4. 编辑布局文件 activity_main.xml

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

    <Button
        android:id="@+id/contactsBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="read contacts" />

</LinearLayout>

增加了一个按钮,用于启动ContactsActivity

  1. 编辑 MainActivity

Java 代码

    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button contactsBtn = findViewById(R.id.contactsBtn);
        contactsBtn.setOnClickListener(view -> {
    
    
            Intent intent = new Intent(this, ContactsActivity.class);
            startActivity(intent);
        });
    }

Kotlin 代码

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val contactsBtn: Button = findViewById(R.id.contactsBtn)
        contactsBtn.setOnClickListener{
    
    
            val intent = Intent(this, ContactsActivity::class.java)
            startActivity(intent)
        }
    }

给按钮增加监听,点击跳转ContactsActivity

  1. 编辑布局文件 activity_contacts.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    android:padding="30dp">

    <TextView
        android:id="@+id/contactsTv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15sp"
        android:hint="contacts" />

</LinearLayout>

TextView用于呈现读取到的联系人数据,这里简化处理了。

  1. 编辑 ContactsActivity

Java 代码

public class ContactsActivity extends AppCompatActivity {
    
    

    private TextView tv;
    private final List<String> contractsList = new LinkedList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_contacts);
        tv = findViewById(R.id.contactsTv);

        mayReadTheContacts();
    }

    private void mayReadTheContacts() {
    
    
        if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.READ_CONTACTS
        )
        ) {
    
    
            ActivityCompat.requestPermissions(this, new String[]{
    
    Manifest.permission.READ_CONTACTS}, 101);
        } else {
    
    
            readTheContacts();
        }
    }

    /**
     * 读取联系人数据
     */
    private void readTheContacts() {
    
    
        contractsList.clear();
        Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
                null, null, null, null);
        // 遍历每一条联系人的数据
        while (cursor.moveToNext()) {
    
    
            // 读取联系人数据在系统中的id,以及联系人名称
            String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
            String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

            // 读取联系人的电话号码
            StringBuilder numbers = new StringBuilder();
            Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id, null, null);
            while (phones.moveToNext()) {
    
    
                String num = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                numbers.append(num).append("  ");
            }
            phones.close();

            // 读取联系人的邮箱
            StringBuilder address = new StringBuilder();
            Cursor mails = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,
                    null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + id, null, null);
            while (mails.moveToNext()) {
    
    
                String mail = mails.getString(mails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
                address.append(mail).append("  ");
            }
            mails.close();
            contractsList.add(String.format("[%s] %s\n%s\n%s", id, name, numbers.toString(), address.toString()));
        }
        cursor.close();

        // 界面显示联系人的数据
        updateUI();
    }

    private void updateUI() {
    
    
        tv.setText("");
        for (String s : contractsList) {
    
    
            tv.append(s);
            tv.append("\n\n");
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    
    
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
    
    
            case 101:
                if (grantResults.length > 0 && PackageManager.PERMISSION_GRANTED == grantResults[0]) {
    
    
                    readTheContacts();
                } else {
    
    
                    Toast.makeText(this, " 你拒绝了读取联系人权限 ", Toast.LENGTH_SHORT).show();
                    finish();
                }

                break;
        }
    }
}

Kotlin 代码

class ContactsActivity : AppCompatActivity() {
    
    

    private lateinit var tv: TextView
    private val contractsList = LinkedList<String>()

    override fun onCreate(savedInstanceState: Bundle?) {
    
    
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_contacts)
        tv = findViewById(R.id.contactsTv)

        mayReadTheContacts()
    }

    private fun mayReadTheContacts() {
    
    
        if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.READ_CONTACTS
            )
        ) {
    
    
            ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_CONTACTS), 101)
        } else {
    
    
            readTheContacts()
        }
    }

    /**
     * 读取联系人数据
     */
    private fun readTheContacts() {
    
    
        contractsList.clear()
        contentResolver.query(
            ContactsContract.Contacts.CONTENT_URI,
            null, null, null, null
        )?.apply {
    
    
            // 遍历每一条联系人的数据
            while (moveToNext()) {
    
    
                // 读取联系人数据在系统中的id,以及联系人名称
                val id = getString(getColumnIndex(ContactsContract.Contacts._ID))
                val name = getString(getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))

                // 读取联系人的电话号码
                val numbers = StringBuilder()
                contentResolver.query(
                    ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = $id", null, null
                )?.apply {
    
    
                    while (moveToNext()) {
    
    
                        val num =
                            getString(getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
                        numbers.append(num).append("  ")
                    }
                    close()
                }

                // 读取联系人的邮箱
                val address = StringBuilder()
                contentResolver.query(
                    ContactsContract.CommonDataKinds.Email.CONTENT_URI,
                    null, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = $id", null, null
                )?.apply {
    
    
                    while (moveToNext()) {
    
    
                        val mail =
                            getString(getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA))
                        address.append(mail).append("  ")
                    }
                    close()
                }
                contractsList.add("[$id] $name\n$numbers\n$address")
            }
            close()

            // 界面显示联系人的数据
            updateUI()
        }
    }

    private fun updateUI() {
    
    
        tv.text = ""
        val it = contractsList.listIterator()
        while (it.hasNext()) {
    
    
            tv.append(it.next())
            tv.append("\n\n")
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
    
    
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
    
    
            101 -> {
    
    
                if (grantResults.isNotEmpty() && PackageManager.PERMISSION_GRANTED == grantResults[0]) {
    
    
                    readTheContacts()
                } else {
    
    
                    Toast.makeText(this, " 你拒绝了读取联系人权限 ", Toast.LENGTH_SHORT).show()
                    finish()
                }
            }
        }
    }
}

函数 mayReadTheContacts() 首先判断用户是否授权读取联系人信息,得到授权之后再去读取联系人信息;
函数 onRequestPermissionsResult() 是用户授权/拒绝的回调;
函数 readTheContacts() 实现了读取联系人信息,然后调用 updateUI() 在界面上显示出来;
Android 使用 ContentResolver 对象来操作共享数据,Activity提供了 getContentResolver() 函数来获取该对象;
使用ContentResolverquery()函数来查询数据。
用到的常量说明:
ContactsContract.Contacts.CONTENT_URI,管理联系人的 Uri;
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,管理联系人手机号码的 Uri;
ContactsContract.CommonDataKinds.Email.CONTENT_URI,管理联系人邮箱账号的 Uri;

  1. 项目运行

首先我们需要在模拟器中添加联系人数据,假如已经有联系人数据了可以忽略这一步;
cs

运行项目;点击项目主页的按钮,跳转至新页面;系统弹窗请求授权读取联系人数据,我们点击允许;
然后页面显示出系统联系人的数据:
demo

项目代码地址

  • Java 版:
    https://github.com/BethelDEV/shaguaAndroid/tree/main/javaSource/ContentProviderSample

  • Kotlin 版:
    https://github.com/BethelDEV/shaguaAndroid/tree/main/kotlinSource/ContentProviderSample

猜你喜欢

转载自blog.csdn.net/flyingyajun/article/details/126427797