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
相关产品推荐
相关产品推荐

