package com.ydl.media.audio.manager import android.annotation.SuppressLint 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.graphics.Color import android.os.Build import androidx.core.app.NotificationCompat import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.RemoteViews import android.widget.TextView import com.bumptech.glide.Glide import com.bumptech.glide.request.target.NotificationTarget import com.ydl.media.R import com.ydl.media.audio.PlayService import com.ydl.media.audio.constants.Extras import com.ydl.media.audio.model.Music import com.ydl.media.audio.receiver.StatusBarReceiver import java.util.* /** * Created by haorui on 2019-10-27 . * Des: 通知管理器 */ class NotifyManager private constructor() { private var playService: PlayService? = null private var notificationManager: NotificationManager? = null private object SingletonHolder { val instance = NotifyManager() } fun init(playService: PlayService) { this.playService = playService notificationManager = playService.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager } fun showPlay(music: Music?) { if (music == null) { return } playService?.startForeground(NOTIFICATION_ID, buildNotification(playService!!, music, true)) } fun showPause(music: Music?) { if (music == null) { return } playService?.stopForeground(false) notificationManager?.notify(NOTIFICATION_ID, buildNotification(playService!!, music, false)) } fun cancelAll() { notificationManager?.cancelAll() } @SuppressLint("WrongConstant") private fun buildNotification( context: Context, music: Music, isPlaying: Boolean ): Notification { val intent = Intent() intent.action= "com.ydl.media.ACTION_MUSIC_CLICK" intent.putExtra(Extras.EXTRA_NOTIFICATION, true) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) var remoteViews = getRemoteViews(context, music, isPlaying) val builder: NotificationCompat.Builder if (Build.VERSION.SDK_INT >= 26) { val channelId = "app_play_intent_service_channel_id" val channelName = "壹点灵心理咨询" val notificationManager = context.getSystemService("notification") as NotificationManager val notificationChannel = NotificationChannel(channelId, channelName, 2) notificationManager.createNotificationChannel(notificationChannel) builder = NotificationCompat.Builder(context, channelId) } else { builder = NotificationCompat.Builder(context) } builder .setContentIntent(pendingIntent) .setSmallIcon(R.drawable.ic_notification) .setCustomContentView(remoteViews) val notification = builder.build() val target = NotificationTarget(context, R.id.iv_icon, remoteViews, notification, NOTIFICATION_ID) Glide.with(context) .asBitmap() .load(music.coverPath) .into(target) return notification } private fun getRemoteViews(context: Context, music: Music, isPlaying: Boolean): RemoteViews { val title = music.title val subtitle = music.artist + "-" + music.album val remoteViews = RemoteViews(context.packageName, R.layout.notification) remoteViews.setTextViewText(R.id.tv_title, title) remoteViews.setTextViewText(R.id.tv_subtitle, subtitle) val isLightNotificationTheme = isLightNotificationTheme(playService) val playIntent = Intent(StatusBarReceiver.ACTION_STATUS_BAR) playIntent.setPackage("com.cxzapp.xinlizixun") playIntent.putExtra(StatusBarReceiver.EXTRA, StatusBarReceiver.EXTRA_PLAY_PAUSE) val playPendingIntent = PendingIntent.getBroadcast(context, 0, playIntent, PendingIntent.FLAG_UPDATE_CURRENT) remoteViews.setImageViewResource( R.id.iv_play_pause, getPlayIconRes(isLightNotificationTheme, isPlaying) ) remoteViews.setOnClickPendingIntent(R.id.iv_play_pause, playPendingIntent) val nextIntent = Intent(StatusBarReceiver.ACTION_STATUS_BAR) nextIntent.setPackage("com.cxzapp.xinlizixun") nextIntent.putExtra(StatusBarReceiver.EXTRA, StatusBarReceiver.EXTRA_NEXT) val nextPendingIntent = PendingIntent.getBroadcast(context, 1, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT) remoteViews.setImageViewResource(R.id.iv_next, getNextIconRes(isLightNotificationTheme)) remoteViews.setOnClickPendingIntent(R.id.iv_next, nextPendingIntent) return remoteViews } private fun getPlayIconRes(isLightNotificationTheme: Boolean, isPlaying: Boolean): Int { return if (isPlaying) { if (isLightNotificationTheme) R.drawable.ic_status_bar_pause_dark_selector else R.drawable.ic_status_bar_pause_light_selector } else { if (isLightNotificationTheme) R.drawable.ic_status_bar_play_dark_selector else R.drawable.ic_status_bar_play_light_selector } } private fun getNextIconRes(isLightNotificationTheme: Boolean): Int { return if (isLightNotificationTheme) R.drawable.ic_status_bar_next_dark_selector else R.drawable.ic_status_bar_next_light_selector } private fun isLightNotificationTheme(context: Context?): Boolean { val notificationTextColor = getNotificationTextColor(context) return isSimilarColor(Color.BLACK, notificationTextColor) } private fun getNotificationTextColor(context: Context?): Int { val builder = NotificationCompat.Builder(context) val notification = builder.build() val remoteViews = notification.contentView ?: return Color.BLACK val layoutId = remoteViews.layoutId val notificationLayout = LayoutInflater.from(context).inflate(layoutId, null) as ViewGroup val title = notificationLayout.findViewById<TextView>(android.R.id.title) return title?.currentTextColor ?: findTextColor(notificationLayout) } /** * 如果通过 android.R.id.title 无法获得 title , * 则通过遍历 notification 布局找到 textSize 最大的 TextView ,应该就是 title 了。 */ private fun findTextColor(notificationLayout: ViewGroup): Int { val textViewList = ArrayList<TextView>() findTextView(notificationLayout, textViewList) val maxTextSize = -1f var maxTextView: TextView? = null for (textView in textViewList) { if (textView.textSize > maxTextSize) { maxTextView = textView } } return maxTextView?.currentTextColor ?: Color.BLACK } private fun findTextView(view: View, textViewList: MutableList<TextView>) { if (view is ViewGroup) { for (i in 0 until view.childCount) { findTextView(view.getChildAt(i), textViewList) } } else if (view is TextView) { textViewList.add(view) } } private fun isSimilarColor(baseColor: Int, color: Int): Boolean { val simpleBaseColor = baseColor or -0x1000000 val simpleColor = color or -0x1000000 val baseRed = Color.red(simpleBaseColor) - Color.red(simpleColor) val baseGreen = Color.green(simpleBaseColor) - Color.green(simpleColor) val baseBlue = Color.blue(simpleBaseColor) - Color.blue(simpleColor) val value = Math.sqrt((baseRed * baseRed + baseGreen * baseGreen + baseBlue * baseBlue).toDouble()) return value < 180.0 } companion object { private val NOTIFICATION_ID = 0x111 fun get(): NotifyManager { return SingletonHolder.instance } } }