You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin如何获取通过Intent跳转添加到系统日历的事件?

Kotlin 实现跳转系统日历添加事件后读取自定义事件

你当前的跳转逻辑已经基本可用,只需要补充返回结果解析、事件查询两部分逻辑即可实现需求:


1. 调整跳转回调,获取新增事件标识

修改registerForActivityResult的返回值类型,系统日历添加事件成功后会在返回Intent中携带新增事件的Uri,我们可以从中解析出事件ID用于后续查询:

// 修改回调契约,返回值改为可空的Long(事件ID,添加失败返回null)
private val addEvent = registerForActivityResult(object : ActivityResultContract<Jdn, Long?>() {
    override fun createIntent(context: Context, input: Jdn): Intent {
        val time = input.toJavaCalendar().timeInMillis
        // 这里建议给事件加唯一标识,方便后续查询过滤,避免拿到其他应用的日历事件
        val appFlag = "your_app_unique_flag"
        return Intent(Intent.ACTION_INSERT)
            .setData(CalendarContract.Events.CONTENT_URI)
            .putExtra(CalendarContract.Events.DESCRIPTION, "自定义事件描述_$appFlag")
            .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, time)
            .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, time)
            .putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, true)
    }

    override fun parseResult(resultCode: Int, intent: Intent?): Long? {
        // 只有操作成功才解析事件ID
        if (resultCode != Activity.RESULT_OK || intent?.data == null) return null
        // 从返回的Uri中提取事件ID
        return try {
            ContentUris.parseId(intent.data!!)
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
}) { eventId ->
    // 回调处触发事件查询
    eventId?.let {
        val event = queryCalendarEvent(it)
        // 拿到事件后自行处理展示逻辑
        event?.let { e ->
            Log.d("CalendarEvent", "事件标题:${e.title},时间:${e.startTime}")
        }
    } ?: run {
        // 添加失败/用户取消操作
        Toast.makeText(this, "未添加日历事件", Toast.LENGTH_SHORT).show()
    }
}

2. 实现日历事件查询方法

通过系统ContentResolver查询日历事件,可根据事件ID精准查询,也可根据你自定义的标识批量查询所有本应用添加的事件:

// 定义日历事件数据类
data class CalendarEvent(
    val id: Long,
    val title: String,
    val description: String?,
    val startTime: Long,
    val endTime: Long,
    val isAllDay: Boolean
)

@RequiresPermission(Manifest.permission.READ_CALENDAR)
private fun queryCalendarEvent(eventId: Long): CalendarEvent? {
    val projection = arrayOf(
        CalendarContract.Events._ID,
        CalendarContract.Events.TITLE,
        CalendarContract.Events.DESCRIPTION,
        CalendarContract.Events.DTSTART,
        CalendarContract.Events.DTEND,
        CalendarContract.Events.ALL_DAY
    )
    // 按事件ID精准查询
    val selection = "${CalendarContract.Events._ID} = ?"
    val selectionArgs = arrayOf(eventId.toString())

    return contentResolver.query(
        CalendarContract.Events.CONTENT_URI,
        projection,
        selection,
        selectionArgs,
        null
    )?.use { cursor ->
        if (cursor.moveToFirst()) {
            CalendarEvent(
                id = cursor.getLong(cursor.getColumnIndexOrThrow(CalendarContract.Events._ID)),
                title = cursor.getString(cursor.getColumnIndexOrThrow(CalendarContract.Events.TITLE)),
                description = cursor.getString(cursor.getColumnIndexOrThrow(CalendarContract.Events.DESCRIPTION)),
                startTime = cursor.getLong(cursor.getColumnIndexOrThrow(CalendarContract.Events.DTSTART)),
                endTime = cursor.getLong(cursor.getColumnIndexOrThrow(CalendarContract.Events.DTEND)),
                isAllDay = cursor.getInt(cursor.getColumnIndexOrThrow(CalendarContract.Events.ALL_DAY)) == 1
            )
        } else null
    }
}

// 如果需要批量查询所有本应用添加的事件,可以用这个方法,过滤你之前加的唯一标识
@RequiresPermission(Manifest.permission.READ_CALENDAR)
private fun queryAllMyAppEvents(): List<CalendarEvent> {
    val appFlag = "your_app_unique_flag"
    val projection = arrayOf(
        CalendarContract.Events._ID,
        CalendarContract.Events.TITLE,
        CalendarContract.Events.DESCRIPTION,
        CalendarContract.Events.DTSTART,
        CalendarContract.Events.DTEND,
        CalendarContract.Events.ALL_DAY
    )
    val selection = "${CalendarContract.Events.DESCRIPTION} LIKE ?"
    val selectionArgs = arrayOf("%$appFlag%")
    val events = mutableListOf<CalendarEvent>()

    contentResolver.query(
        CalendarContract.Events.CONTENT_URI,
        projection,
        selection,
        selectionArgs,
        "${CalendarContract.Events.DTSTART} DESC"
    )?.use { cursor ->
        while (cursor.moveToNext()) {
            events.add(
                CalendarEvent(
                    id = cursor.getLong(cursor.getColumnIndexOrThrow(CalendarContract.Events._ID)),
                    title = cursor.getString(cursor.getColumnIndexOrThrow(CalendarContract.Events.TITLE)),
                    description = cursor.getString(cursor.getColumnIndexOrThrow(CalendarContract.Events.DESCRIPTION)),
                    startTime = cursor.getLong(cursor.getColumnIndexOrThrow(CalendarContract.Events.DTSTART)),
                    endTime = cursor.getLong(cursor.getColumnIndexOrThrow(CalendarContract.Events.DTEND)),
                    isAllDay = cursor.getInt(cursor.getColumnIndexOrThrow(CalendarContract.Events.ALL_DAY)) == 1
                )
            )
        }
    }
    return events
}

3. 权限配置注意事项

  • 需要在AndroidManifest.xml中声明权限:
<uses-permission android:name="android.permission.READ_CALENDAR" />
<!-- 如果后续需要直接在应用内修改/删除日历事件,再加WRITE_CALENDAR权限 -->
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
  • 确保调用跳转逻辑前已经动态申请到READ_CALENDAR权限,Android 6.0及以上系统必须动态申请。

内容的提问来源于stack exchange,提问作者Mahdi Razzaghi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 11:15:03