相關知識
權限宣告與請求
CONTACTS 屬於危險權限,所以除了要在 AndroidManifest.xml 中宣告權限,還得在運行時請求權限許可。
ContentURI
存取 Contacts (聯絡人) 的 URI 為: ContactsContract.CommonDataKinds.Phone.*CONTENT_URI*
顯示名稱的欄位:ContactsContract.CommonDataKinds.Phone.*DISPLAY_NAME*
電話欄位:ContactsContract.CommonDataKinds.Phone.*NUMBER*
ContentResolver
這裏我們只會用到 ContentResolver 的 query() 功能,
val cursor = contentResolver.query(
uri, // ContentURI
projection, // 指定查詢的欄位名稱
selection, // 指定 WHERE 的條件
selectionArgs, // 為 WHERE 的佔位符號提供實際值
sortOrder) // 指定資料排序
使用範例
// 查詢 todos 資料表的所有資料,取得所有欄位
val cursor = contentResolver.query(
Uri.parse("content://app.kirin.android.provider/todos"),
null,
null,
null,
null)
while(cursor.moveToNext()) {
val title = cursor.getString(cursor.getColumnIndex("title"))
}
cursor.close()
程式實作
建立含有一個 EmptyActivity 的專案: ContentResolver Lab
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="<http://schemas.android.com/apk/res/android>"
package="app.kirin.android.contentresolverlab">
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ContentResolverLab">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lv_contacts" />
</LinearLayout>
MainActivity.kt
package app.kirin.android.contentresolverlab
import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.provider.ContactsContract
import android.widget.ArrayAdapter
import android.widget.ListView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity() {
private val contactsList = ArrayList<String>()
private lateinit var adapter : ArrayAdapter<String>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
adapter = ArrayAdapter(this, android.R.layout.simple_list_item_1, contactsList)
val lvContacts = findViewById<ListView>(R.id.lv_contacts)
lvContacts.adapter = adapter
val permissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { result ->
if (result) {
showContacts()
} else {
Toast.makeText(this, "必須同意權限請求才能繼續使用", Toast.LENGTH_SHORT).show()
}
}
if(ContextCompat.checkSelfPermission(
this, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
showContacts()
} else {
permissionLauncher.launch(Manifest.permission.READ_CONTACTS)
}
}
private fun showContacts() {
contentResolver.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, null, null, null)?.apply {
while(moveToNext()) {
val displayName = getString(getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME))
val number = getString(getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
contactsList.add("$displayName\\n$number")
}
adapter.notifyDataSetChanged()
close()
}
}
}
Comments