本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在Android开发中,联系人、通话记录和短信管理是满足用户基本通讯需求的关键功能。本文将介绍如何利用Kotlin语言实现联系人和通话记录的填充,以及短信操作的相关方法。内容包括使用ContentResolver访问联系人数据、请求权限、创建联系人和通话记录、发送和处理短信的详细步骤。本文还将探讨FillingTools压缩包中的工具类,这些工具类能够简化测试环境中的数据填充过程,但需确保遵守用户隐私政策。
联系人

1. 联系人管理与填充

在Android开发中,联系人管理是用户交互的基础组件之一。为了提供良好的用户体验,开发者需要熟练掌握联系人的添加、更新以及查询等功能。本章将带领读者进入联系人管理的世界,并通过实际代码示例,展示如何高效地填充和管理联系人数据。

1.1 联系人数据模型

首先,要对联系人数据有一个清晰的认识。联系人模型通常包含姓名(name)、电话号码(phoneNumber)、邮箱(email)等字段。这些信息构成了Android通讯录的基本单位,即 ContentProvider 中的 ContactsContract.Data

1.2 填充联系人数据

接下来,我们需要了解如何填充这些数据。这涉及到使用 ContentResolver ContentProvider 来插入、更新和查询联系人。例如,通过 insert() 方法可以添加新的联系人记录,而 update() 方法则用于更新已存在联系人的信息。

val values = ContentValues().apply {
    put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
    put(ContactsContract.CommonDataKinds.Phone.NUMBER, "1234567890")
    put(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, "John Doe")
}

// 插入联系人
val uri: Uri = context.contentResolver.insert(ContactsContract.Data.CONTENT_URI, values)

通过上述代码示例,我们可以看到在Android中添加一个新的联系人记录是多么直接和简洁。开发者通过精确指定数据类型和值,可以轻松地管理联系人信息。本章的后续部分将进一步探讨高级联系人管理技术,以及如何与现代Kotlin语言无缝集成。

2. 通话记录管理与填充

2.1 通话记录的数据结构和填充原理

2.1.1 通话记录数据的字段和含义

在Android系统中,通话记录数据被存储在系统数据库中的 calls 表,其中每个通话记录由多个字段组成,这些字段详细记录了通话的各种信息。常见的字段包括:

  • _id :通话记录的唯一标识符。
  • number :通话对方的电话号码。
  • type :通话类型,例如:来电、拨出、未接来电等。
  • date :通话发生的具体日期和时间。
  • duration :通话持续的时间,单位是毫秒。
  • call_type :通话的子类型,例如:国际通话、本地通话等。
  • features :通话的特性,例如:视频通话、VoIP通话等。

理解这些字段对于开发应用来管理通话记录是至关重要的,这将帮助我们从原始数据中提取有用信息。

2.1.2 通话记录填充的方法和技巧

填充通话记录通常需要模拟通话记录数据,以便在测试或开发过程中使用。我们可以通过编写脚本或者使用专门的测试工具来填充通话记录。以下是几种方法:

  • 使用Android Debug Bridge (ADB): 利用ADB的 shell 命令可以方便地添加通话记录,例如:
    bash adb shell content insert --uri content://call_log/calls --bind name:s:_id --bind value:i:1 \ --bind name:s:date --bind value:i:1599471652408 \ --bind name:s:_data --bind value:s:INCOMING_TYPE \ --bind name:s:duration --bind value:i:120000 ...
    该命令通过指定字段来插入一条通话记录。

  • 编写自定义脚本: 开发人员可以使用Java代码或Python脚本来调用Android API进行通话记录的填充。

2.2 通话记录的存储和读取

2.2.1 通话记录在Android中的存储方式

Android系统将通话记录存储在内部数据库中,通常位于 /data/data/com.android.providers.calllog/databases/ 目录下的 call_log.db 文件。该数据库文件是SQLite格式,因此可以通过SQLite命令或者数据库管理工具访问。

2.2.2 通话记录的读取方法和技巧

要读取通话记录,应用程序需要具有读取通话记录的权限。以下是使用Android API读取通话记录的代码示例:

Cursor cursor = getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
    do {
        String phoneNumber = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
        int callType = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));
        Date callDate = new Date(cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE)));
        long duration = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DURATION));
        // 处理获取到的通话记录信息...
    } while (cursor.moveToNext());
    cursor.close();
}

在此代码块中,我们首先通过 getContentResolver().query 方法查询通话记录,然后遍历游标(Cursor)获取每条通话记录的具体信息,最后关闭游标。

通话记录的管理是联系人管理系统中重要的部分,合理地处理和优化这些数据不仅可以提升用户体验,还能提高应用的性能。在下一节中,我们将探讨短信操作与管理的相关知识。

3. 短信操作与管理

在本章中,我们将深入探讨Android平台下的短信操作与管理,重点分析短信的数据结构、操作方法以及存储和读取的机制。短信功能是移动应用中最基础也是最常用的通信方式之一,因此,了解其背后的工作原理对于开发功能完善的通讯类应用至关重要。

3.1 短信的数据结构和操作方法

短信服务是移动设备中不可或缺的一部分,它允许用户发送和接收文本消息。在这一小节中,我们将从数据结构和操作方法两个维度来深入探讨短信功能的实现。

3.1.1 短信数据的字段和含义

短信服务的主要数据结构是 SmsMessage ,它包含了一系列的字段,每一个字段都有其特定的含义。下表列出了 SmsMessage 类中一些重要的字段及其解释:

字段名 类型 含义
address String 发送或接收短信的电话号码
messageBody String 短信的内容
timestamp long 短信发送或接收的时间戳
status int 短信的状态,例如:已发送、已接收、已提交等
serviceCenter String 短信服务中心的地址,用于显示短信是通过哪个服务中心发送的
locked boolean 是否为锁定状态,锁定的短信不能被删除
type int 短信类型,如:普通短信(0)、回执报告(1)、发送报告(2)等

3.1.2 发送和接收短信的方法和技巧

在Android中,发送短信通常需要使用 SmsManager 类,而接收短信则需要使用 BroadcastReceiver 监听 SMS_RECEIVED_ACTION 动作。以下是发送和接收短信的基本流程和代码示例:

发送短信
import android.telephony.SmsManager

// 获取SmsManager实例
val smsManager = SmsManager.getDefault()
// 将要发送的短信内容拆分为70字节的部分(因为一条短信最多70字节)
val parts = smsManager.divideMessage(messageBody)
// 遍历短信各部分并发送
parts.forEach { part ->
    smsManager.sendTextMessage(address, null, part, null, null)
}

逻辑分析:
- getDefault() 方法用于获取 SmsManager 的默认实例。
- divideMessage 方法将长短信内容拆分成多个小于70字节的部分,以满足短信发送的限制。
- sendTextMessage 方法负责发送拆分后的单个短信部分,其中 address 为接收方电话号码, message 为短信内容。

接收短信
class SmsReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        when (intent.action) {
            TelephonyIntents.ACTION.Telephony_Sms_Received -> {
                val pdus = intent.getParcelableArrayExtra(TelephonyIntents.EXTRA.Incoming_Sms_Pdu)
                for (pdu in pdus) {
                    val smsMessage = SmsMessage.createFromPdu(pdu as ByteArray)
                    val messageBody = smsMessage.messageBody
                    val address = smsMessage.originatingAddress
                    // 处理短信内容和发送者信息
                }
            }
        }
    }
}

逻辑分析:
- BroadcastReceiver 用于接收短信广播。
- onReceive 方法是接收广播后的回调函数,在这个方法中,我们检查意图(Intent)动作是否是短信接收动作。
- getParcelableArrayExtra 方法从广播中提取短信PDU(Protocol Data Units),然后我们遍历PDU数组,每个PDU转换成 SmsMessage 对象,从而可以访问短信内容和发送者地址。

3.2 短信的存储和读取

短信数据的存储和读取是确保应用功能完整性的重要环节。在本小节中,我们将探讨在Android平台上短信如何被存储,以及如何高效地读取这些短信数据。

3.2.1 短信在Android中的存储方式

Android系统中的短信数据通常存储在 /data/data/com.android.providers.telephony/databases/mmssms.db 的SQLite数据库中。该数据库包含多个表,其中 sms 表存储了短信的详细信息。以下是 sms 表中一些重要的列:

列名 类型 含义
_id integer 短信的唯一ID
address text 发送或接收短信的电话号码
body text 短信内容
type integer 短信类型
date integer 短信的时间戳(毫秒)
read integer 是否已读
status integer 短信的状态
thread_id integer 线程ID,代表与该短信相关的所有短信的分组

3.2.2 短信的读取方法和技巧

为了读取存储在数据库中的短信数据,我们可以使用SQLite数据库API或者利用 ContentProvider ,后者是一种更简洁、安全的方法。以下是使用 ContentProvider 读取短信内容的代码示例:

// 获取ContentResolver实例
val contentResolver = context.contentResolver
// 定义要查询的字段
val projection = arrayOf(
    Sms.Inbox.ADDRESS,
    Sms.Inbox.BODY,
    Sms.Inbox.DATE,
    Sms.Inbox.READ,
    Sms.Inbox.STATUS,
    Sms.Inbox.THREAD_ID
)
// 使用ContentResolver查询短信内容
val cursor = contentResolver.query(
    Sms.Inbox.CONTENT_URI,
    projection,
    null,
    null,
    null
)

// 遍历Cursor获取短信数据
if (cursor != null && cursor.moveToFirst()) {
    do {
        val address = cursor.getString(cursor.getColumnIndex(Sms.Inbox.ADDRESS))
        val body = cursor.getString(cursor.getColumnIndex(Sms.Inbox.BODY))
        val date = cursor.getLong(cursor.getColumnIndex(Sms.Inbox.DATE))
        val read = cursor.getInt(cursor.getColumnIndex(Sms.Inbox.READ))
        val status = cursor.getInt(cursor.getColumnIndex(Sms.Inbox.STATUS))
        val threadId = cursor.getInt(cursor.getColumnIndex(Sms.Inbox.THREAD_ID))

        // 处理获取到的短信数据
    } while (cursor.moveToNext())
    cursor.close()
}

逻辑分析:
- ContentResolver 是访问内容提供者的主要接口。
- query 方法用于执行查询操作,通过指定URI( Sms.Inbox.CONTENT_URI ),我们能够访问收件箱中的短信。
- projection 数组定义了我们想要查询的短信字段。
- Cursor 对象是查询结果集的游标,它允许我们逐行访问查询结果。

通过上述的示例代码,我们可以清楚地看到,使用 ContentProvider 来查询短信数据是如何操作的。需要注意的是,从Android 6.0 (API level 23)开始,获取短信的权限需要动态请求,以确保用户隐私和数据安全。

4. Kotlin语言在Android通讯模块的应用

4.1 Kotlin语言的基本语法和特性

4.1.1 Kotlin语言的数据类型和变量

Kotlin语言中数据类型和变量的声明相比于Java来说更为简洁和直观。Kotlin中的基本数据类型包括数值类型、字符类型、布尔类型和字符串类型。这些基本类型的变量声明不需要显式指定类型,因为Kotlin有类型推断功能,可以让编译器自动推断出变量的类型。

val number: Int = 42 // 显式类型声明
val decimal = 3.14 // 类型推断
val character: Char = 'c'
val isBoolean = true
val text = "Hello, Kotlin!"

在上面的示例中, val 关键字用于声明不可变的变量(值不可更改),相当于Java中的 final 变量。如果需要一个可以重新赋值的变量,则使用 var 关键字。

在Kotlin中,字符串插值是一个非常有用的功能,允许直接在字符串中嵌入表达式:

val name = "Kotlin"
val greeting = "Hello, $name!" // 使用$符号插入变量
val expression = "${greeting.replace(" ", "")}, welcome to ${text}."

4.1.2 Kotlin语言的控制结构和函数

控制结构在Kotlin中也更为精简。例如条件语句可以省略大括号,直接返回表达式的值,而不需要像Java那样使用 return 关键字。

val max = if (a > b) a else b // 简洁的if表达式

当需要处理包含多个条件的逻辑时,Kotlin的 when 表达式提供了类似 switch 的功能,但是更加灵活和强大:

val result = when {
    number == 1 -> "one"
    number == 2 -> "two"
    else -> "many"
}

Kotlin函数的声明使用 fun 关键字,并且可以拥有默认参数值,允许在调用函数时提供或省略某些参数。

fun greet(name: String, time: String = "morning") {
    println("Good $time, $name!")
}

// 调用带有默认参数的函数
greet("Alice") // 输出: Good morning, Alice!
greet("Bob", "evening") // 输出: Good evening, Bob!

4.2 Kotlin语言在通讯模块的应用

4.2.1 Kotlin语言实现联系人填充

在Android应用开发中,使用Kotlin语言实现联系人填充可以利用扩展函数来简化操作。通过Kotlin的 ContentResolver 扩展,我们可以方便地查询和插入联系人数据。

val contentResolver = context.contentResolver
// 插入新的联系人
fun insertContact(contactName: String, contactPhone: String) {
    val values = ContentValues().apply {
        put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
        put(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, contactName)
        put(ContactsContract.CommonDataKinds.Phone.NUMBER, contactPhone)
    }
    contentResolver.insert(ContactsContract.Data.CONTENT_URI, values)
}

4.2.2 Kotlin语言实现通话记录和短信操作

Kotlin同样适用于实现通话记录和短信操作的逻辑。通过使用Kotlin协程,我们可以轻松实现异步操作而不会阻塞主线程,同时保持代码的可读性和简洁性。

// 异步插入通话记录
suspend fun insertCallLog(callType: String, phoneNumber: String, duration: Int) {
    withContext(Dispatchers.IO) {
        val values = ContentValues().apply {
            put(CallLog.Calls.NUMBER, phoneNumber)
            put(CallLog.Calls.TYPE, CallLog.Calls.incomingType(callType))
            put(CallLog.Calls.DURATION, duration)
        }
        contentResolver.insert(CallLog.Calls.CONTENT_URI, values)
    }
}

// 读取短信内容
fun readSms(threadId: Long): List<String> {
    val messages = mutableListOf<String>()
    val uri = ContentUris.withAppendedId(Sms.CONTENT_URI, threadId)
    val cursor = contentResolver.query(uri, arrayOf(Sms.ADDRESS, Sms.BODY), null, null, null)
    cursor.use {
        while (it?.moveToNext() == true) {
            val address = it.getString(0)
            val body = it.getString(1)
            messages.add("$address: $body")
        }
    }
    return messages
}

4.2.3 Kotlin与Java互操作性

虽然Kotlin与Java的互操作性是非常强大的,但是在实际项目中,总会有一些Java库或者Android框架的API并不直接支持Kotlin。为了在Kotlin中使用这些API,我们可以借助Kotlin的 @JvmStatic 注解, @JvmOverloads 注解等,使Kotlin的扩展方法和属性在Java代码中看起来就像是原生Java类的一部分。

class Utils {
    companion object {
        @JvmStatic fun add(a: Int, b: Int) = a + b
    }
}

在Java中,你可以这样调用上述Kotlin函数:

int result = Utils.add(3, 4);

这显示了Kotlin到Java的互操作性,使得在Kotlin项目中复用Java库变得非常平滑。

5. 权限请求与处理

5.1 Android权限系统的原理和机制

5.1.1 Android权限系统的结构和类型

在Android操作系统中,权限系统是保障用户隐私和系统安全的重要机制。权限分为多种类型,其结构主要分为系统权限和应用权限。系统权限通常包括一些系统级的操作,如读取电话状态、访问网络等。应用权限则是针对单个应用的权限请求,如获取位置信息、访问相机等。

Android权限系统分为普通权限、危险权限和特殊权限三类:

  • 普通权限(Normal Permissions) :这类权限一般不会对用户的隐私造成风险,系统通常会自动授予这些权限,无需用户同意。例如,设置时区的权限。
  • 危险权限(Dangerous Permissions) :涉及到用户隐私或者可能对设备的正常运行产生影响的权限,需要用户明确授权。例如,读取联系人的权限就属于危险权限。这类权限的请求会显示在运行时的弹窗中,用户可以选择允许或拒绝。
  • 特殊权限(Special Permissions) :这类权限通常涉及到底层硬件或敏感数据的访问,需要通过特殊的声明和处理方式。例如,修改系统设置权限,这种权限通常需要系统级签名或者root权限。

5.1.2 Android权限系统的工作原理

Android权限系统的工作原理可以概括为以下几点:

  1. 权限声明 :在应用的 AndroidManifest.xml 文件中声明所需的权限,系统会根据这些声明决定应用能否执行相关操作。

  2. 权限请求 :当应用尝试执行需要特定权限的操作时,系统会检查该应用是否已获得相应权限。如果没有,系统会弹出对话框提示用户,让用户来决定是否授权。

  3. 权限授予与拒绝 :用户可以选择同意授权或拒绝。如果用户授权,应用就可以执行相关操作;如果用户拒绝,应用则无法执行需要该权限的操作。

  4. 权限管理 :用户可以在设置中查看和管理已经授权的权限。用户可以随时更改授权状态,这对于管理隐私和安全非常有用。

5.2 权限请求与处理的方法和技巧

5.2.1 权限请求的方法和技巧

在Android开发中,请求权限是一个必须细心处理的环节。以下是请求权限的一些方法和技巧:

// 请求单个权限
ActivityCompat.requestPermissions(
    this,
    arrayOf(Manifest.permission.READ_CONTACTS),
    MY_PERMISSIONS_REQUEST_READ_CONTACTS
)

// 请求多个权限
ActivityCompat.requestPermissions(
    this,
    arrayOf(Manifest.permission.READ_CONTACTS, Manifest.permission.CALL_PHONE),
    MY_PERMISSIONS_REQUEST_MULTIPLE_PERMISSIONS
)
  • 请求单个权限 :使用 requestPermissions 方法,并传入权限数组,其中只包含一个权限名称。

  • 请求多个权限 :如果有多个权限需要请求,权限名称数组可以包含多个权限名称。

  • 权限结果处理 :在 onRequestPermissionsResult 回调方法中处理权限结果。

  • 解释权限用途 :在请求权限之前,向用户解释为什么需要这些权限。这样可以提高用户授权的可能性。

  • 动态权限检查 :在请求权限前,应先检查是否已经获得了权限。若已授权,则无需再次请求。

  • 设计良好的权限请求流程 :不要在应用启动时就请求所有权限,这样会降低用户体验。可以将权限请求分散到实际需要的时候进行。

5.2.2 权限处理的方法和技巧

一旦用户对权限请求做出了选择,我们需要根据用户的选择做出响应。以下是权限处理的一些方法和技巧:

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    when (requestCode) {
        MY_PERMISSIONS_REQUEST_READ_CONTACTS -> {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 权限被授予,更新UI或执行操作
            } else {
                // 权限被拒绝,更新UI或给出提示
            }
            return
        }

        // 处理多个权限请求的回调
        MY_PERMISSIONS_REQUEST_MULTIPLE_PERMISSIONS -> {
            var allPermissionsGranted = true
            for (grantResult in grantResults) {
                if (grantResult != PackageManager.PERMISSION_GRANTED) {
                    allPermissionsGranted = false
                    break
                }
            }
            if (allPermissionsGranted) {
                // 所有权限被授予,执行操作
            } else {
                // 至少有一个权限被拒绝,给出提示或引导用户前往设置页面开启权限
            }
        }
    }
}
  • 检查授权结果 :通过 grantResults 数组检查每个权限请求的授权结果。

  • 适当反馈 :根据授权结果,给用户适当的反馈。比如,如果权限被拒绝,可以提示用户拒绝权限的后果,并引导用户前往设置中手动开启权限。

  • 恢复操作 :如果用户拒绝权限,应用应能够优雅地恢复到权限请求之前的状态,并提供替代的操作方式。

  • 动态权限请求 :即使用户在初次使用时拒绝了权限请求,应用应提供机会在应用内部重新请求权限。

  • 定期检查 :在应用的生命周期中的某些关键时刻,例如在从后台恢复或者应用配置更改后,再次检查权限是否已经被授予,确保应用能够正常运行。

通过遵循以上方法和技巧,可以确保应用在遵守用户隐私政策的前提下,正确地处理权限请求与处理,提高用户体验和应用的稳定性。

6. 工具类 ContactFiller CallLogFiller 的应用和 SmsUtils 工具类实现短信功能

6.1 工具类 ContactFiller CallLogFiller 的原理和应用

6.1.1 工具类 ContactFiller CallLogFiller 的结构和功能

ContactFiller CallLogFiller 是针对Android通讯模块而设计的实用工具类。它们旨在简化和自动化联系人和通话记录数据的填充和测试过程。

  • ContactFiller :负责创建、更新、删除以及查询联系人信息。
  • CallLogFiller :用于插入、读取和清除通话记录数据。

这两个工具类在内部使用了Android的 ContentProvider ContentResolver 接口,并与它们的URI结构紧密配合,以模拟真实的通讯数据操作。

6.1.2 工具类 ContactFiller CallLogFiller 的应用和实践

在开发实践中, ContactFiller CallLogFiller 可以被用来批量填充测试数据,快速构建测试环境,或者用于性能测试。

使用示例代码:

// 填充联系人数据
val contactFiller = ContactFiller(context)
contactFiller.addContact("John Doe", "+123456789", "john.doe@example.com")

// 添加通话记录
val callLogFiller = CallLogFiller(context)
callLogFiller.addCallLog(CallLog.Calls.INCOMING_TYPE, "123456789", Date().time)

以上代码展示了如何利用工具类 ContactFiller CallLogFiller 来填充单个联系人和通话记录。在测试和开发过程中,这些类可以显著提升效率和重现性。

6.2 工具类 SmsUtils 的原理和应用

6.2.1 工具类 SmsUtils 的结构和功能

SmsUtils 是专门用于处理短信发送和接收的工具类。它能够帮助开发者模拟发送和接收短信,并在不需要真实发送短信的情况下进行测试。

  • 提供发送短信的接口。
  • 提供接收短信的接口。
  • 模拟短信收件箱,用于存储和检索短信内容。

6.2.2 工具类 SmsUtils 的应用和实践

SmsUtils 可以用于自动化测试,同时也可以在没有发送短信权限的设备上模拟短信服务,以便进行功能测试。

使用示例代码:

// 发送短信
SmsUtils.sendSms(context, "123456789", "Test message")

// 模拟接收短信
SmsUtils.receiveSms(context, "123456789", "Received test message")

这段代码展示了如何使用 SmsUtils 来模拟发送和接收短信。开发者可以在应用中集成此类,以实现复杂的短信功能测试。

6.3 遵守用户隐私政策的重要性

6.3.1 用户隐私政策的含义和重要性

在当今的数字时代,用户隐私政策是保护用户个人信息和数据安全的法律依据。对于Android开发者而言,确保应用符合隐私政策不仅是法律要求,也是建立用户信任的关键。

6.3.2 如何在开发中遵守用户隐私政策

  • 明确告知用户应用的数据使用目的。
  • 只收集应用运行所必须的最少数据。
  • 提供用户数据访问和删除的选项。
  • 实施加密措施,保护用户数据不被未授权访问。

开发者在处理个人数据时,应始终以透明、合法、公正、必要为原则,确保用户的知情权和选择权得到尊重。

通过本章,我们了解了如何通过 ContactFiller CallLogFiller SmsUtils 工具类优化通讯模块的测试和开发工作,并强调了遵守用户隐私政策的重要性。在后续章节中,我们将进一步探讨如何处理Android权限请求与处理。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在Android开发中,联系人、通话记录和短信管理是满足用户基本通讯需求的关键功能。本文将介绍如何利用Kotlin语言实现联系人和通话记录的填充,以及短信操作的相关方法。内容包括使用ContentResolver访问联系人数据、请求权限、创建联系人和通话记录、发送和处理短信的详细步骤。本文还将探讨FillingTools压缩包中的工具类,这些工具类能够简化测试环境中的数据填充过程,但需确保遵守用户隐私政策。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐