Android自定义告诉完结

前语

自定义告诉便是运用自定义的布局,完结自定义的功能。

Notification的惯例布局中能够设置标题、内容、巨细图标,也能够完结点击跳转等。

惯例的布局固然便利,可当需求变多就只能运用自定义布局了。

我想要完结的告诉布局除了时刻、标题、图标、跳转外,还有“5分钟后提示”、“已知悉”这两个功能需求完结。如下图所示:

Android自定义定时通知实现

正文

一、待办数据库

1、待办实体类

Android自定义定时通知实现

假定现在时刻是12点,增加了一个14点的待办会议,并设置提早20分钟进行提示

其间year、month、day、time构成会议的时刻,也便是今日的14点content是待办的内容。remind是该待办提早提示的时刻,也便是20分钟type是待办类型,包括未完结,已完结和疏忽

2、数据拜访Dao

增加或更新一条待办事项

Android自定义定时通知实现

@Insert(onConflict = OnConflictStrategy.REPLACE) 注解: 如果指定 id 的目标没有保存在数据库中, 就会新增一条数据到数据库。如果指定 id 的目标数据已经保存到数据库中, 就会删除掉本来的数据, 然后新增一条数据。

3、数据库封装

在库房层的TodoStoreRepository类中对待办数据库的操作进行封装。不赘述了。

二、增加守时器

每条待办都对应着一个守时使命,在用户增加一条待办数据的一起需求增加一条对应的守时使命。在这里运用映射的方式,将待办的Id和守时使命逐个绑定。

1、思路:

  1. 首要要构造一个Map<Long, TimerTask>>类型的参数和一个守时器Timer。
  2. 在增加守时使命前,先对待办数据进行过滤。
  3. 计算出延迟的时刻。
  4. 守时器调度,当触发时,消息弹窗提示。

2、完结

Android自定义定时通知实现

说明

  • isOver() — 判别该待办有没有完结,通过待办的type进行判别。

代码:fun isOver() = type == 1

  • delayTime — 延迟时刻。获取到当时时刻的时刻戳、将待办提示的时刻转化为时刻戳,最后相减,得到一个Long类型的时刻戳即延迟时刻。

  • 当delayTime大于0时,进行守时器调度,将待办Id与守时使命绑定,当延迟时刻抵达时会触发守时器使命,守时器使命中包含了消息弹窗提示。

3、封装

Android自定义定时通知实现

在 TodoScheduleUseCase 类中将待办数据刺进和待办守时器创建封装在一起了,刺进数据后获取到数据的Id,将id赋值传给待办守时器使命。

三、注册播送

1. 首要创建一个TodoNotifyReceiver播送

Android自定义定时通知实现

在TodoNotifyReceiver中,首要获取到待办数据,根据Action判别播送的类型并执行相应的回调。

2. 自定义Action

分别是“5分钟后提示”、“已知悉”的Action

Android自定义定时通知实现

3. 播送注册办法

Android自定义定时通知实现

4.播送注册及回调完结

“5分钟后提示”完结是调用delayTodoTask5min办法,原理便是将remind即提示时刻减5达到五分钟后提示的作用。并撤销该告诉。再将修改正特点的待办重新增加到待办列表中。

“已知悉”完结是调用markTodoTaskDone办法,原理便是将type特点标记成1,代表已完结。并撤销该告诉。再将修改正特点的待办重新增加到待办列表中。

Android自定义定时通知实现

/**
 * 延迟5分钟
 */
fun delayTodoTask5min(todoInfo: TodoInfo) {
    useScope.launch {
        todoInfo.remind -= 5
        insertOrUpdateTodo(todoInfo)
    }
}
/**
 * 标记已完结
 */
fun markTodoTaskDone(todoInfo: TodoInfo) {
    useScope.launch {
        todoInfo.type = 1
        insertOrUpdateTodo(todoInfo)
    }
}

四、自定义告诉构建

fun showNotify(todoInfo: TodoInfo) {
    binding = LayoutTodoNotifyItemBinding.inflate(context.layoutInflater())
    // 自定义告诉布局
    val notificationLayout =
        RemoteViews(context.packageName, R.layout.layout_todo_notify_item)
    // 设置自定义的Action
    val notifyAfterI = Intent().setAction(TodoNotifyReceiver.TODO_CHANGE_ACTION)
    val alreadyKnowI = Intent().setAction(TodoNotifyReceiver.TODO_ALREADY_KNOW_ACTION)
    // 传入TodoInfo
    notifyAfterI.putExtra("todoInfo", todoInfo)
    alreadyKnowI.putExtra("todoInfo", todoInfo)
    // 设置点击时跳转的界面
    val intent = Intent(context, MarketActivity::class.java)
    val pendingIntent = PendingIntent.getActivity(context, todoInfo.id.toInt(), intent, PendingIntent.FLAG_CANCEL_CURRENT)
    val notifyAfterPI = PendingIntent.getBroadcast(context, todoInfo.id.toInt(), notifyAfterI, PendingIntent.FLAG_CANCEL_CURRENT)
    val alreadyKnowPI = PendingIntent.getBroadcast(context, todoInfo.id.toInt(), alreadyKnowI, PendingIntent.FLAG_CANCEL_CURRENT)
    //给告诉布局中的组件设置点击事情
    notificationLayout.setOnClickPendingIntent(R.id.notify_after, notifyAfterPI)
    notificationLayout.setOnClickPendingIntent(R.id.already_know, alreadyKnowPI)
    // 构建自定义告诉布局
    notificationLayout.setTextViewText(R.id.notify_content, todoInfo.content)
    notificationLayout.setTextViewText(R.id.notify_date, "${todoInfo.year}-${todoInfo.month + 1}-${todoInfo.day}    ${todoInfo.time}")
    var notifyBuild: NotificationCompat.Builder? = null
    // 构建NotificationChannel
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val notificationChannel = NotificationChannel(context.packageName, "todoNotify", NotificationManager.IMPORTANCE_HIGH)
        notificationChannel.lockscreenVisibility = Notification.VISIBILITY_SECRET
        notificationChannel.enableLights(true) // 是否在桌面icon右上角展示小红点
        notificationChannel.lightColor = Color.RED// 小红点色彩
        notificationChannel.setShowBadge(true) // 是否在久按桌面图标时显示此渠道的告诉
        notificationManager.createNotificationChannel(notificationChannel)
        notifyBuild = NotificationCompat.Builder(context, todoInfo.id.toString())
        notifyBuild.setChannelId(context.packageName);
    } else {
        notifyBuild = NotificationCompat.Builder(context)
    }
    notifyBuild.setSmallIcon(R.mipmap.icon_todo_item_normal)
        .setStyle(NotificationCompat.DecoratedCustomViewStyle())
        .setCustomContentView(notificationLayout) //设置自定义告诉布局
        .setPriority(NotificationCompat.PRIORITY_MAX) //设置优先级
        .setAutoCancel(true) //设置点击后撤销Notification
        .setContentIntent(pendingIntent) //设置跳转
        .build()
    notificationManager.notify(todoInfo.id.toInt(), notifyBuild.build())
    // 撤销指定id的告诉
    fun cancelNotifyById(id: Int) {
        notificationManager.cancel(id)
    }
}

过程:

  1. 构建自定义告诉布局
  2. 设置自定义的Action
  3. 传入待办数据
  4. 设置点击时跳转的界面
  5. 设置了两个BroadcastReceiver类型的点击回调
  6. 给告诉布局中的组件设置点击事情
  7. 构建自定义告诉布局
  8. 构建NotificationChannel
  9. 增加撤销指定id的告诉办法

总结

以上,Android自定义守时告诉完结的过程和成果。文章若出现错误,欢迎各位批评指正,写文不易,转载请注明出处谢谢。