1.权限
android 13版本 将通知改为运行时权限,需要向用户动态申请权限。
// 权限请求
implementation 'com.guolindev.permissionx:permissionx:1.7.1'
2.通知工具类
通知了解:官网
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import com.choryan.quan.videowzproject.R
import com.choryan.quan.videowzproject.activity.ActivityHome
import com.choryan.quan.videowzproject.activity.ActivityStart
import com.choryan.quan.videowzproject.base.AppBase
import com.choryan.quan.videowzproject.extension.ExtensionLog.log
import com.choryan.quan.videowzproject.net.ApiUtlis
import com.permissionx.guolindev.PermissionX
/**
* 描述:
* 作者: shawn
* 时间: 2024/6/311:55
*/
object UtilNotification {
const val scene_code_cid = "cid"
const val scene_code_red = "getRedPackage"
const val scene_code_custom = "custom"
const val key_from = "fromNotification"
private val context = AppBase.instance
private const val notification_id = 123
private const val notification_channel_id = "channel_reward_user"
private const val notification_channel_name = "channel_reward"
private const val notification_channel_description = "让您获取更多奖励的通道"
private var preSendTime: Long = 0L
private fun isFastSend(): Boolean {
if (System.currentTimeMillis() - preSendTime < 500){
return true
}
preSendTime = System.currentTimeMillis()
return false
}
fun requestNotification(activityHome: ActivityHome,action: (Boolean) -> Unit) {
PermissionX.init(activityHome)
.permissions(PermissionX.permission.POST_NOTIFICATIONS)
.onExplainRequestReason { scope, deniedList ->
val message = "授予通知权限,防止您错过重要消息"
scope.showRequestReasonDialog(deniedList, message, "允许", "拒绝")
}
.request { allGranted, grantedList, deniedList ->
if (allGranted) {
"通知权限已获取".log()
} else {
"通知权限被拒绝 $deniedList".log()
}
action.invoke(allGranted)
}
}
fun createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is not in the Support Library.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = notification_channel_name
val descriptionText = notification_channel_description
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(notification_channel_id, name, importance).apply {
description = descriptionText
}
channel.enableVibration(true)
channel.vibrationPattern = longArrayOf(0)
// Register the channel with the system.
val notificationManager: NotificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
fun sendNotification(sceneCode:String) {
if (isFastSend()) {
return
}
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Get the layouts to use in the custom notification.
val notificationLayout = getRemoteView(sceneCode)
val notificationLayoutExpanded = getRemoteView(sceneCode)
// Create an explicit intent for an Activity in your app.
val intent = Intent(context, ActivityStart::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
intent.putExtra(key_from, sceneCode)
val pendingIntent: PendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
} else {
val flag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_UPDATE_CURRENT else 0
PendingIntent.getActivity(context, 0, intent, flag)
}
// Apply the layouts to the notification.
val customNotification =
NotificationCompat.Builder(context, notification_channel_id)
.setSmallIcon(R.mipmap.app_icon_yghj)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
.setCustomBigContentView(notificationLayoutExpanded)
.setContentIntent(pendingIntent)// Set the intent that fires when the user taps the notification.
.setAutoCancel(true)
.setPriority(NotificationManager.IMPORTANCE_HIGH)
.setCategory(NotificationCompat.CATEGORY_RECOMMENDATION)
.build()
if (PermissionX.isGranted(context, PermissionX.permission.POST_NOTIFICATIONS)) {
notificationManager.notify(notification_id, customNotification)
} else {
"发送通知,但是没有权限".log()
}
}
private fun getRemoteView(sceneCode: String): RemoteViews {
val remoteViews = RemoteViews(ApiUtlis.packageName, R.layout.notification_layout)
when (sceneCode) {
scene_code_cid -> {
remoteViews.setImageViewResource(R.id.iv, R.drawable.ic_notification_1)
}
scene_code_red -> {
remoteViews.setImageViewResource(R.id.iv, R.drawable.ic_notification_2)
}
else -> {
remoteViews.setImageViewResource(R.id.iv, R.drawable.ic_notification_3)
}
}
return remoteViews
}
}
关于通知需要注意的地方:
- android 8.0以上需要创建通知渠道
- pendingIntent创建的flag,需要适配不同版本。传的flag不对,导致intent携带的数据不能获取到,从而无法处理额外的逻辑
- 从onCreate中获取点击通知传递的数据:val from = intent.getStringExtra(key)
3.快捷方式
import android.content.Intent
import android.os.Build
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import com.choryan.quan.videowzproject.R
import com.choryan.quan.videowzproject.activity.ActivityStart
import com.choryan.quan.videowzproject.base.AppBase
/**
* 描述:快捷方式
* 作者: shawn
* 时间: 2024/6/312:04
*/
object UtilShortcut {
val context = AppBase.instance
const val action_key = "shortcut_action_key"
const val action_id_1 = "shortcut_action_1"
const val action_id_2 = "shortcut_action_2"
fun initShortcut() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
val id1 = action_id_1
val intent1 = Intent(Intent.ACTION_MAIN, null, context, ActivityStart::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
putExtra(action_key, id1)
}
val short1 = ShortcutInfoCompat.Builder(context, id1)//唯一标识id
.setShortLabel(context.getString(R.string.shortcut_label_1))//短标签
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_1))//图标
//跳转的目标,定义Activity
.setIntent(intent1)
.build()
val id2 = action_id_2
val intent2 = Intent(Intent.ACTION_MAIN, null, context, ActivityStart::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
putExtra(action_key, id2)
}
val short2 = ShortcutInfoCompat.Builder(context, id2)//唯一标识id
.setShortLabel(context.getString(R.string.shortcut_label_2))//短标签
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_2))//图标
// 跳转的目标,定义Activity
.setIntent(intent2)
.build()
// 执行添加操作
ShortcutManagerCompat.addDynamicShortcuts(context, mutableListOf(short1, short2))
}
}
}
点击快捷方式跳转:
//在onCreate中获取数据
val value = _intent.extras?.getString(UtilShortcut.action_key)
注意:
- 给intent添加flags:Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK,因为有些系统只会把应用从后台拉到前台,相关的生命周期和事件并不会触发。不符合需求的预期