当前位置:   article > 正文

Android-系统日历功能相关_安卓应用开发 日历

安卓应用开发 日历

Android-系统日历功能相关


一、需求描述

  1. 需求1:用户在预约了APP某个活动后,自动把这个活动添加日历中,活动开始前几分钟提醒
  2. 需求2:添加到日历按钮,用户点击后跳转到日历,同时把相关信息带过去,用户在自己确认提醒时间

二、需求具体实现

1、【需求2】实现(不需要权限)

直接打开手机日历APP。

/**
* scheme 只有部分手机支持scheme设置
*/
fun Context.addCalendar(title: String?, des: String?,scheme:String?) {
        val startMillis: Long = System.currentTimeMillis()+60*1000
        val endMillis: Long = System.currentTimeMillis() + 60*5
        val tz = TimeZone.getDefault()
        val intent = Intent(Intent.ACTION_INSERT)
            .setData(CalendarContract.Events.CONTENT_URI)
            .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis)
            .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endMillis)
            .putExtra(CalendarContract.Events.TITLE, title)
            .putExtra(CalendarContract.Events.DESCRIPTION, des)
            .putExtra(CalendarContract.Events.EVENT_LOCATION, tz.displayName)
            .putExtra(CalendarContract.Events.CUSTOM_APP_PACKAGE, packageName)
            .putExtra(CalendarContract.Events.CUSTOM_APP_URI, scheme)  
        startActivity(intent)
}    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

2、【需求1】相关实现(需要权限)

1)、权限申请和判断

日历权限是需要动态申请,所有需要在AndroidManifest.xml中添加

<uses-permission android:name="android.permission.READ_CALENDAR"/>
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
  • 1
  • 2

同时

//判断是否具有权限  
fun checkPermission(context: AppCompatActivity): Boolean {
        return context.hasPermission(Manifest.permission.WRITE_CALENDAR, Manifest.permission.READ_CALENDAR, isRequest = true)
}

fun AppCompatActivity.hasPermission(vararg permissions: String, isRequest: Boolean = true): Boolean {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true
    val permissionsCheck: MutableList<String> = ArrayList()
    for (permission in permissions) {
        if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            permissionsCheck.add(permission)
        }
    }
    if (permissionsCheck.isEmpty()) return true
    if (isRequest) {
        ActivityCompat.requestPermissions(this as Activity, permissionsCheck.toTypedArray(), 100)
    }
    return false
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
2)、日历编辑
1.添加用户

因为所有的日历编辑都需要一个用户所有需要一个用户

    /**
     * 检查是否已经添加了日历账户,如果没有添加先添加一个日历账户再查询
     * 获取账户成功返回账户id,否则返回-1
     */
    private fun checkAndAddCalendarAccount(context: Context): Int {
        val oldId = checkCalendarAccount(context)
        return if (oldId >= 0) {
            oldId
        } else {
            val addId = addCalendarAccount(context)
            if (addId >= 0) {
                checkCalendarAccount(context)
            } else {
                -1
            }
        }
    }

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

    /**
     * 添加日历账户,账户创建成功则返回账户id,否则返回-1
     */
    private fun addCalendarAccount(context: Context): Long {
        val 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_DISPLAY_NAME)
        value.put(CalendarContract.Calendars.VISIBLE, 1)
        value.put(CalendarContract.Calendars.CALENDAR_COLOR, Color.BLUE)
        value.put(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL, CalendarContract.Calendars.CAL_ACCESS_OWNER)
        value.put(CalendarContract.Calendars.SYNC_EVENTS, 1)
        value.put(CalendarContract.Calendars.CALENDAR_TIME_ZONE, timeZone.id)
        value.put(CalendarContract.Calendars.OWNER_ACCOUNT, CALENDARS_ACCOUNT_NAME)
        value.put(CalendarContract.Calendars.CAN_ORGANIZER_RESPOND, 0)
        var calendarUri = Uri.parse(CALENDER_URL)
        calendarUri = calendarUri.buildUpon()
                .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
                .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, CALENDARS_ACCOUNT_NAME)
                .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, CALENDARS_ACCOUNT_TYPE)
                .build()
        val result = context.contentResolver.insert(calendarUri, value)
        return if (result == null) -1 else ContentUris.parseId(result)
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
2.添加日历事件

这里回返回日历的id,用来更新或者删除,只有部分手机支持scheme设置

     /**
     * @param remindTime 提醒的事件
     * @param previousTime 提前时间分钟开始提示
     * @param packageName 包名
     * @param scheme 部分手机支持跳转
     */
	fun addCalendarEvent(context: Context?, title: String?, des: String?,
						 remindTime: Long,endTime: Long?, previousTime: Long, packageName: String? = null, scheme: String? = null): Long {
        if (context == null) {
            return -1
        }
        val calId = checkAndAddCalendarAccount(context) //获取日历账户的id
        if (calId < 0) { //获取账户id失败直接返回,添加日历事件失败
            return -1
        }

        //添加日历事件
        val mCalendar = Calendar.getInstance()
        mCalendar.timeInMillis = remindTime //设置开始时间
        val start = mCalendar.time.time
        mCalendar.timeInMillis = start + 10 * 60 * 1000 //设置终止时间,开始时间加10分钟
        val end = endTime ?: mCalendar.time.time
        val event = ContentValues()
        event.put(CalendarContract.Events.TITLE, title)
        event.put(CalendarContract.Events.DESCRIPTION, des)
        event.put(CalendarContract.Events.CALENDAR_ID, calId) //插入账户的id
        event.put(CalendarContract.Events.DTSTART, start)
        event.put(CalendarContract.Events.DTEND, end)
        event.put(CalendarContract.Events.HAS_ALARM, 1) //设置有闹钟提醒
        event.put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().displayName) //这个是时区,必须有
        event.put(CalendarContract.Events.CUSTOM_APP_PACKAGE, packageName)
        event.put(CalendarContract.Events.CUSTOM_APP_URI, scheme)
        val newEvent = context.contentResolver.insert(Uri.parse(CALENDER_EVENT_URL), event)
                ?: //添加日历事件失败直接返回
                return -1//添加事件

        //事件提醒的设定
        val values = ContentValues()
        val eventID = ContentUris.parseId(newEvent)
        values.put(CalendarContract.Reminders.EVENT_ID, eventID)
        values.put(CalendarContract.Reminders.MINUTES, previousTime) // 提前previousDate分钟有提醒
        values.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT)
        context.contentResolver.insert(Uri.parse(CALENDER_REMINDER_URL), values)
                ?: //添加事件提醒失败直接返回
                return -1
        return eventID
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
3.更新日历事件

需要上面addCalendarEvent返回的日历id

  fun updateRemindEvent(context: Context, calId: Int, eventId: Long, title: String?, des: String?,
                          remindTime: Long,
                          endTime: Long?,
                          previousTime: Long, packageName: String? = null, scheme: String? = null): Boolean {

        val mCalendar = Calendar.getInstance()
        mCalendar.timeInMillis = remindTime //设置开始时间
        val start = mCalendar.time.time
        mCalendar.timeInMillis = start + 10 * 60 * 1000 //设置终止时间,开始时间加10分钟
        val end = endTime ?: mCalendar.time.time

        return try {
            val tz = TimeZone.getDefault()        // 获取默认时区
            /* 更新日程 */
            val values = ContentValues()
            values.put(CalendarContract.Events.DTSTART, start)
            values.put(CalendarContract.Events.DTEND, end)
            values.put(CalendarContract.Events.TITLE, title)
            values.put(CalendarContract.Events.DESCRIPTION, des)
            values.put(CalendarContract.Events.CALENDAR_ID, calId)
            values.put(CalendarContract.Events.ACCESS_LEVEL, CalendarContract.Events.ACCESS_DEFAULT)
            values.put(CalendarContract.Events.EVENT_LOCATION, tz.displayName)
            values.put(CalendarContract.Events.EVENT_TIMEZONE, tz.id)
            val updateUri = ContentUris.withAppendedId(Uri.parse(CALENDER_REMINDER_URL), eventId)
            val rowNum = context.contentResolver.update(updateUri, values, null, null)
            if (rowNum <= 0) {
                /*更新event不成功,说明用户在日历中删除了提醒事件,重新添加*/
                if (addCalendarEvent(context, title, des, remindTime, endTime, previousTime, packageName, scheme) != -1L) {
                    return true
                }
                return false
            } else {
                val reminderValues = ContentValues()
                reminderValues.put(CalendarContract.Reminders.MINUTES, previousTime) // 提前提醒
                val rUri = Uri.parse(CALENDER_REMINDER_URL)
                context.contentResolver.update(rUri, reminderValues, CalendarContract.Reminders.EVENT_ID + "= ?", arrayOf(eventId.toString()))
                true
            }
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
4.删除日历事件

需要上面addCalendarEvent返回的日历id

fun deleteCalendarEvent(context: Context, id: Long): Int {
        val deleteUri = ContentUris.withAppendedId(Uri.parse(CALENDER_EVENT_URL), id)
        return context.contentResolver.delete(deleteUri, null, null)
}
  • 1
  • 2
  • 3
  • 4
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/750727
推荐阅读
相关标签
  

闽ICP备14008679号