package com.gh.base 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 android.os.Bundle import android.preference.PreferenceManager import android.text.TextUtils import android.view.View import androidx.core.app.NotificationCompat import com.gh.common.notifier.Notifier import com.gh.common.util.EntranceUtils import com.gh.common.util.MtaHelper import com.gh.common.util.StringUtils import com.gh.common.util.toObject import com.gh.gamecenter.R import com.gh.gamecenter.entity.PushEntity import com.gh.gamecenter.entity.PushMessageEntity import com.gh.gamecenter.entity.PushMessageUnreadEntity import com.gh.gamecenter.entity.PushNotificationEntity import com.gh.gamecenter.manager.UserManager import com.gh.gamecenter.message.MessageUnreadRepository import com.gh.gamecenter.qa.answer.detail.AnswerDetailActivity import com.gh.gamecenter.receiver.UmengMessageReceiver import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_CLICK import com.gh.gamecenter.receiver.UmengMessageReceiver.Companion.TYPE_REMOVE import com.gh.gamecenter.retrofit.Response import com.gh.gamecenter.retrofit.RetrofitManager import com.google.gson.Gson import com.umeng.message.UmengMessageService import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import okhttp3.MediaType import okhttp3.RequestBody import okhttp3.ResponseBody import org.android.agoo.common.AgooConstants import org.json.JSONObject import retrofit2.HttpException import java.util.* class GHUmengNotificationService : UmengMessageService() { companion object { const val ACTION_UMENG = "com.gh.gamecenter.UMENG" const val MESSAGE_FROM_SYSTEM = "message_from_system" const val HALO_MESSAGE_DIALOG = "HALO_MESSAGE_DIALOG" const val HALO_MESSAGE_CENTER = "HALO_MESSAGE_CENTER" const val ANSWER = "answer" const val FOLLOW_QUESTION = "follow_question" const val NOTIFICATION_ID = 2015 const val DISPLAY_TYPE_NOTIFICATION = "notification" const val DISPLAY_TYPE_CUSTOM = "custom" const val MESSAGE_ID = "message_id" const val NOTIFICATION_MESSAGE_ID = "notification_message_id" // 通知中心消息 ID const val PUSH_ID = "push_id" } val notificationTags = arrayOf("GH_UMENG_TAG_1", "GH_UMENG_TAG_2", "GH_UMENG_TAG_3") val gson = Gson() override fun onMessage(context: Context, intent: Intent) { val message = intent.getStringExtra(AgooConstants.MESSAGE_BODY) val isMessageFromSystem = intent.getBooleanExtra(MESSAGE_FROM_SYSTEM, false) try { val pushData = message.toObject() pushData?.let { handlePushData(context, it, message, isMessageFromSystem) } } catch (e: Exception) { e.printStackTrace() } } private fun handlePushData(context: Context, pushData: PushEntity, message: String, isMessageFromSystem: Boolean) { val notificationManager = context.applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager if (pushData.displayType == DISPLAY_TYPE_NOTIFICATION) { // 其它类型的透传信息 // 显示到通知栏 val msg = message.toObject() val data = msg?.extra?.data // 系统推送(非自定义信息),直接处理跳转 if (isMessageFromSystem) { val intent = Intent() intent.setClass(context, UmengMessageReceiver::class.java) intent.putExtra(EntranceUtils.KEY_DATA, data?.link) intent.putExtra(EntranceUtils.KEY_TYPE, UmengMessageReceiver.DIRECT_ONLY) intent.putExtra(EntranceUtils.KEY_MESSAGE, message) intent.putExtra(NOTIFICATION_MESSAGE_ID, data?.messageId) context.sendBroadcast(intent) return } // 用户未登录的情况下不生成消息中心通知,避免用户掉登录了还收到跳转至消息中心的通知 if (data != null && data.link?.target == "system" && !UserManager.getInstance().isLoggedIn) { return } val clickIntent = Intent() val removeIntent = Intent() clickIntent.setClass(context, UmengMessageReceiver::class.java) clickIntent.putExtra(EntranceUtils.KEY_DATA, data?.link) clickIntent.putExtra(EntranceUtils.KEY_MESSAGE, message) clickIntent.putExtra(MESSAGE_ID, msg?.msgId) clickIntent.putExtra(PUSH_ID, data?.pushId) clickIntent.putExtra(NOTIFICATION_MESSAGE_ID, data?.messageId) clickIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_CLICK) removeIntent.setClass(context, UmengMessageReceiver::class.java) removeIntent.putExtra(EntranceUtils.KEY_TYPE, TYPE_REMOVE) removeIntent.putExtra(EntranceUtils.KEY_MESSAGE, message) val clickPendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt(), clickIntent, PendingIntent.FLAG_UPDATE_CURRENT) val deletePendingIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis().toInt() + 1, removeIntent, PendingIntent.FLAG_UPDATE_CURRENT) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel("Halo_Push", "Halo_Push", NotificationManager.IMPORTANCE_DEFAULT) notificationManager.createNotificationChannel(channel) } val notification = NotificationCompat.Builder(context, "Halo_Push") .setSmallIcon(R.drawable.ic_notification) .setTicker(pushData.body?.ticker) .setContentTitle(pushData.body?.title) .setContentText(pushData.body?.text) .setContentIntent(clickPendingIntent) .setDeleteIntent(deletePendingIntent) .build() notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL notificationManager.notify(getNotificationTag(context), NOTIFICATION_ID, notification) } else { if (UserManager.getInstance().isLoggedIn && HALO_MESSAGE_DIALOG == pushData.body?.custom) { // 回答了问题或者关注了问题的消息 val msg = gson.fromJson(message, PushMessageEntity::class.java) val data = msg?.extra?.data val type = if (ANSWER == data?.type) { "回答了你的问题" } else { "回答了你关注的问题" } val userName = StringUtils.shrinkStringWithDot(data?.userEntity?.name, 8) val displayText = userName + type if (Notifier.isActivityValid(CurrentActivityHolder.getCurrentActivity()) && Notifier.shouldShowNotifier(data?.answer?.id + displayText)) { Notifier.create(CurrentActivityHolder.getCurrentActivity()) .setText(displayText) .setDuration(5000) .setIcon(data?.userEntity?.icon) .setOnClickListener(View.OnClickListener { val bundle = Bundle() bundle.putString(EntranceUtils.KEY_ANSWER_ID, data?.answer?.id) bundle.putString(EntranceUtils.KEY_ENTRANCE, EntranceUtils.ENTRANCE_UMENG) bundle.putString(EntranceUtils.KEY_TO, AnswerDetailActivity::class.java.name) EntranceUtils.jumpActivity(context, bundle) MtaHelper.onEvent("消息弹窗", type, "Does not contains any parameter.") // 标记已读 val jsonObject = JSONObject() jsonObject.put("type", type) val body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString()) RetrofitManager.getInstance(application).api.postMessageRead(UserManager.getInstance().userId, data?.id, body) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : Response() { override fun onResponse(response: ResponseBody?) { super.onResponse(response) MessageUnreadRepository.loadMessageUnreadData() } override fun onFailure(e: HttpException?) { e?.printStackTrace() } }) Notifier.hide() }) .show(false) Notifier.tagNotifierAsShowed(data?.answer?.id + displayText) } } else if (HALO_MESSAGE_CENTER == pushData.body?.custom) { // 消息中心逻辑 val msg = gson.fromJson(message, PushMessageUnreadEntity::class.java) val data = msg?.extra?.data data?.let { MessageUnreadRepository.loadMessageUnreadData() } } } } /** * 规则:最多三条消息,以旧换新 * * @return NotificationTag */ private fun getNotificationTag(context: Context): String { val sp = PreferenceManager.getDefaultSharedPreferences(context) val edit = sp.edit() val timeTagMap = HashMap() for (tag in notificationTags) { val time = sp.getLong(tag, 0) if (time == 0L) { edit.putLong(tag, System.currentTimeMillis()).apply() return tag } else { timeTagMap[time] = tag } } val minTime = Collections.min(timeTagMap.keys) val tag = timeTagMap[minTime] edit.putLong(tag, System.currentTimeMillis()).apply() return if (TextUtils.isEmpty(tag)) notificationTags[0] else tag!! } }