日历行程插入记录

借助本次与h5的活动联调需求,梳理下从查询日历权限->权限申请→完成插入反馈的整个链路

兼容版本权限配置包括两部分

1、清单文件

<!-- 日历读写权限   -->
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />

2、动态权限申请

沿用项目中原有方法

xxx.checkPermission(arrayOf(
            Manifest.permission.WRITE_CALENDAR, Manifest.permission.READ_CALENDAR
        ), object : XXCallBack() {
            override fun onAllGranted(allRequestedPermissions: Array<String>) {
                if (allRequestedPermissions.size == 2
                    && allRequestedPermissions[0] == Manifest.permission.WRITE_CALENDAR
                    && allRequestedPermissions[1] == Manifest.permission.READ_CALENDAR
                ) {
                   // 这里进行日历行程插入操作
                }
            }
            ...
        })

日历插入行程

1、检查日历账户

存在账户的前提下在进行插入操作,无则需要手动创建一个

/**
 * 检查是否存在现有账户,存在则返回账户id,否则返回-1
 */
@WorkerThread
private fun checkCalendarAccount(context: Context): Int {
    val cursor: Cursor? =
        context.contentResolver.query(Uri.parse(CALENDER_URL), null, null, null, null)
    return cursor.use { userCursor ->
        if (userCursor == null) { //查询返回空值
            return -1
        }
        val count: Int = userCursor.count
        if (count > 0) { //存在现有账户,取第一个账户的id返回
            userCursor.moveToFirst()
            userCursor.getInt(userCursor.getColumnIndex(CalendarContract.Calendars._ID))
        } else {
            -1
        }
    }
}


/**
 * 添加日历账户,账户创建成功则返回账户id,否则返回-1
 */
@WorkerThread
private fun addCalendarAccount(context: Context): Long {
    val timeZone: TimeZone = TimeZone.getDefault()
    val value = ContentValues()
    value.put(CalendarContract.Calendars.NAME, CALENDARS_NAME) // 存储的列名
    value.put(CalendarContract.Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME) // 名称,与类型成对对应
    value.put(CalendarContract.Calendars.ACCOUNT_TYPE, CALENDARS_ACCOUNT_TYPE) // 类型
    value.put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,
        CALENDARS_ACCOUNT_NAME) // 日历的显示名称
    value.put(CalendarContract.Calendars.OWNER_ACCOUNT, CALENDARS_ACCOUNT_NAME) // 日历所有者的账户
    ...
    val result: Uri? = context.contentResolver.insert(calendarUri, value)
    return if (result == null) -1 else ContentUris.parseId(result)
}

2、插入行程

1、首先插入事件event

val events = ContentValues()
events.put(CalendarContract.Instances.TITLE, calendarBean.title) // 标题
events.put(CalendarContract.Instances.DESCRIPTION, calendarBean.desc) // 描述
events.put(CalendarContract.Instances.CALENDAR_ID, calId) //插入账户的id
events.put(CalendarContract.Instances.DTSTART, calendarBean.start ?: 0) //设置开始时间
events.put(CalendarContract.Instances.DTEND, calendarBean.end ?: 0) // 设置终止时间
events.put(CalendarContract.Instances.HAS_ALARM, 1) //设置有闹钟提醒
Pug.print(TAG, "TimeZone.getDefault()==${TimeZone.getDefault().id}")
events.put(CalendarContract.Instances.EVENT_TIMEZONE,
    TimeZone.getDefault().id) //这个是时区,必须有

ContentProviderOperation.newInsert(Uri.parse(CALENDER_EVENT_URL))
    .withValues(events)
    .build()

2、根据插入event返回的对应的eventId插入提醒行程

val reminders = ContentValues()
reminders.put(CalendarContract.Reminders.EVENT_ID, ContentUris.parseId(result.uri))
reminders.put(CalendarContract.Reminders.MINUTES, 0) // 提前previousDate天有提醒
reminders.put(CalendarContract.Reminders.METHOD,
    CalendarContract.Reminders.METHOD_ALERT)
ContentProviderOperation.newInsert(Uri.parse(CALENDER_REMINDER_URL))
    .withValues(reminders)
    .build()

注:如果批量插入的事件字段完全相同可以使用:CalendarContract.Events.RRULE定义重复规则

这里提醒事件可能h5会传递多个,所以选用了ContentProviderOperation做ContentProvider的批量插入,减少执行事务次数。

3、整体插入代码

/**
 * 添加日历事件
 */
@WorkerThread
fun addCalendarEvent(
    context: Context,
    list: List<CalendarBean>,
): Boolean {
    val calId = checkAndAddCalendarAccount(context) //获取日历账户的id
    if (calId < 0) { //获取账户id失败直接返回,添加日历事件失败
        return false
    }
    // 1、插入event事件 2、根据插入的事件id插入行程 3、根据最终的插入结果数返回是否完成此次插入任务
    val bulkInsertNumber = list.map { calendarBean ->
        val events = ContentValues()
        events.put(CalendarContract.Instances.TITLE, calendarBean.title) // 标题
        events.put(CalendarContract.Instances.DESCRIPTION, calendarBean.desc) // 描述
        events.put(CalendarContract.Instances.CALENDAR_ID, calId) //插入账户的id
        events.put(CalendarContract.Instances.DTSTART, calendarBean.start ?: 0) //设置开始时间
        events.put(CalendarContract.Instances.DTEND, calendarBean.end ?: 0) // 设置终止时间
        events.put(CalendarContract.Instances.HAS_ALARM, 1) //设置有闹钟提醒
        Pug.print(TAG, "TimeZone.getDefault()==${TimeZone.getDefault().id}")
        events.put(CalendarContract.Instances.EVENT_TIMEZONE,
            TimeZone.getDefault().id) //这个是时区,必须有

        ContentProviderOperation.newInsert(Uri.parse(CALENDER_EVENT_URL))
            .withValues(events)
            .build()
    }.let { opsEvent ->
        context.contentResolver.applyBatch(CalendarContract.AUTHORITY,
            opsEvent as ArrayList<ContentProviderOperation>).map { result ->
            val reminders = ContentValues()
            reminders.put(CalendarContract.Reminders.EVENT_ID, ContentUris.parseId(result.uri))
            reminders.put(CalendarContract.Reminders.MINUTES, 0) // 提前previousDate天有提醒
            reminders.put(CalendarContract.Reminders.METHOD,
                CalendarContract.Reminders.METHOD_ALERT)
            ContentProviderOperation.newInsert(Uri.parse(CALENDER_REMINDER_URL))
                .withValues(reminders)
                .build()
        }.let { opsReminds ->
            context.contentResolver.applyBatch(CalendarContract.AUTHORITY,
                opsReminds as ArrayList<ContentProviderOperation>)
        }
    }
    return bulkInsertNumber != null && bulkInsertNumber.size == list.size
}

官方文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值