Files
assistant-android/app/src/main/java/com/gh/common/util/DownloadNotificationHelper.kt
2020-01-14 15:41:41 +08:00

161 lines
7.5 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.gh.common.util
import android.app.Notification
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 androidx.core.app.NotificationCompat
import com.gh.common.AppExecutor
import com.gh.common.constant.Constants
import com.gh.gamecenter.R
import com.halo.assistant.HaloApp
import com.lightgame.download.DownloadEntity
import com.lightgame.download.DownloadStatus
object DownloadNotificationHelper {
private const val DOWNLOAD_GROUP_KEY = "download_group_key"
private const val DOWNLOAD_CHANNEL_ID = "download"
private const val DOWNLOAD_NOTIFICATION_FOLD_ID = 889
private const val DOWNLOAD_NOTIFICATION_ID = 888
private const val PROGRESS_MAX = 100
const val ACTION_INSTALL = "com.gh.gamecenter.INSTALL"
const val ACTION_DOWNLOAD = "com.gh.gamecenter.DOWNLOAD"
private val mNotifyMap: MutableMap<String, Long> = mutableMapOf()
private fun getNotificationManager(): NotificationManager {
return HaloApp.getInstance().application.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}
@JvmStatic
@Synchronized
fun addOrUpdateDownloadNotification(entity: DownloadEntity) {
var requireUpdateNotificationGroupDelay = false
val notificationManager = getNotificationManager()
val downloadNotificationId = (entity.gameId + entity.packageName).hashCode()
val intent = Intent()
if (entity.status == DownloadStatus.done) {
intent.putExtra(EntranceUtils.KEY_DATA, entity.toJson())
intent.putExtra(EntranceUtils.KEY_PATH, entity.path)
intent.action = ACTION_INSTALL
} else {
intent.action = ACTION_DOWNLOAD
}
val pendingIntent = PendingIntent.getBroadcast(HaloApp.getInstance().application,
downloadNotificationId,
intent,
PendingIntent.FLAG_UPDATE_CURRENT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// importance == IMPORTANCE_DEFAULT 时每次更新都会触发震动
val channel = NotificationChannel(DOWNLOAD_CHANNEL_ID, DOWNLOAD_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)
notificationManager.createNotificationChannel(channel)
}
val whenTime = 1000 * 60 * (System.currentTimeMillis() / 1000 / 60)
val builder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
.setContentTitle(entity.name)
.setSmallIcon(R.mipmap.logo)
.setContentIntent(pendingIntent)
.setGroup(DOWNLOAD_GROUP_KEY)
.setWhen(whenTime)
.setProgress(PROGRESS_MAX, entity.percent.toInt(), false)
when (entity.status) {
DownloadStatus.downloading -> builder.setContentText(String.format("%s(剩%s)",
SpeedUtils.getSpeed(entity.speed),
SpeedUtils.getRemainTime(entity.size, entity.progress, entity.speed * 1024)))
DownloadStatus.done -> builder.setContentText("下载完成,点击立即安装")
DownloadStatus.waiting -> builder.setContentText("等待中")
DownloadStatus.subscribe,
DownloadStatus.timeout,
DownloadStatus.neterror -> builder.setContentText("已暂停连接WiFi自动下载")
else -> builder.setContentText("暂停中")
}
when {
entity.status == DownloadStatus.done -> {
builder.setSortKey("A")
builder.setOngoing(true) // 垃圾华为 sortKey 不起效 priority 也不起效,要将下载完成任务的通知置顶只能设置为 ongoing喷了
}
entity.status == DownloadStatus.downloading -> builder.setSortKey("B")
else -> builder.setSortKey("C")
}
val notification = builder.build()
notification.flags = notification.flags or Notification.FLAG_NO_CLEAR
if (entity.status == DownloadStatus.delete
|| entity.status == DownloadStatus.cancel
|| entity.status == DownloadStatus.hijack
|| entity.status == DownloadStatus.notfound
|| entity.status == DownloadStatus.overflow
|| (entity.status == DownloadStatus.done // 触发安装事件以后也 cancel 掉通知
&& !entity.meta[Constants.MARK_ALREADY_TRIGGERED_INSTALLATION].isNullOrEmpty())) {
requireUpdateNotificationGroupDelay = true
notificationManager.cancel(entity.path, DOWNLOAD_NOTIFICATION_ID)
} else {
if (entity.status != DownloadStatus.downloading) {
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
} else {
val time = mNotifyMap[entity.path]
val curTime = System.currentTimeMillis()
if (time == null || curTime - time > 2000) {
mNotifyMap[entity.path] = curTime
notificationManager.notify(entity.path, DOWNLOAD_NOTIFICATION_ID, notification)
}
}
}
if (requireUpdateNotificationGroupDelay) {
// 虽然运行到这里时 notification 已经被 cancel 了,但在下面的 notificationManager.getActiveNotifications 里它有可能还是 active 状态,
// 这里延时 100 ms 避免出现所有的任务都取消了以后依旧有一条 notification group 常驻
AppExecutor.uiExecutor.executeWithDelay(Runnable { updateNotificationGroup() }, 100)
} else {
updateNotificationGroup()
}
}
private fun updateNotificationGroup() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val notificationManager = getNotificationManager()
val activeNotifications = notificationManager.activeNotifications
var downloadNotificationSize = 0
var downloadGroupNotificationSize = 0
for (activeNotification in activeNotifications) {
if (activeNotification.id == DOWNLOAD_NOTIFICATION_ID) {
downloadNotificationSize++
}
if (activeNotification.id == DOWNLOAD_NOTIFICATION_FOLD_ID) {
downloadGroupNotificationSize++
}
}
if (downloadNotificationSize == 0 && downloadGroupNotificationSize != 0) {
// 删除组可能会把组内所有通知一并删除
notificationManager.cancel(DOWNLOAD_NOTIFICATION_FOLD_ID)
} else if (downloadNotificationSize != 0 && downloadGroupNotificationSize == 0) {
val groupBuilder = NotificationCompat.Builder(HaloApp.getInstance().application, DOWNLOAD_CHANNEL_ID)
.setSmallIcon(R.mipmap.logo)
.setGroup(DOWNLOAD_GROUP_KEY)
.setGroupSummary(true)
.setStyle(NotificationCompat.BigTextStyle().bigText("下载任务"))
val groupNotification = groupBuilder.build()
groupNotification.flags = groupNotification.flags or Notification.FLAG_NO_CLEAR
notificationManager.notify(DOWNLOAD_NOTIFICATION_FOLD_ID, groupNotification)
}
}
}
@JvmStatic
fun initDownloadNotification(downloadTasks: MutableList<DownloadEntity>) {
for (downloadTask in downloadTasks) {
addOrUpdateDownloadNotification(downloadTask)
}
}
}