Skip to content

Instantly share code, notes, and snippets.

@zerobranch
Last active February 5, 2021 11:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zerobranch/9ca5b38cb05dcefc8a15d5c566a28a8f to your computer and use it in GitHub Desktop.
Save zerobranch/9ca5b38cb05dcefc8a15d5c566a28a8f to your computer and use it in GitHub Desktop.
Android push notification handler
<service
android:name=".services.FirebaseMessageService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import timber.log.Timber
import javax.inject.Inject
class FirebaseMessageService : FirebaseMessagingService() {
@Inject
lateinit var pushNotificationManager: PushNotificationManager
@Inject
lateinit var settingsUseCase: SettingsUseCase
override fun onCreate() {
super.onCreate()
}
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
val notificationData = remoteMessage.data["custom_notification"]
val notificationId = remoteMessage.data["notification_id"]
Timber.tag("PushNotification").d("Received push notification: $notificationData")
Timber.tag("PushNotification").d("Notification id: $notificationId")
pushNotificationManager.showNotification(notificationId, notificationData)
}
override fun onNewToken(token: String) {
super.onNewToken(token)
settingsUseCase.setPushToken(token)
}
}
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 androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import com.google.gson.GsonBuilder
import kotlin.random.Random
class PushNotificationManager(private val context: Context) {
companion object {
private const val DEFAULT_GROUP_KEY = "my_package.DEFAULT_GROUP"
private const val DEFAULT_CHANNEL_ID = "default_channel_id"
private const val PUSH_DATA_KEY = "push_data_key"
private const val NOTIFICATION_ID_KEY = "notification_id_key"
}
private val gson by lazy { GsonBuilder().create() }
private val notificationManager by lazy { NotificationManagerCompat.from(context) }
init {
deleteOldNotificationChannels()
createNotificationChannels()
}
fun showNotification(notificationId: String?, jsonData: String?) {
jsonData?: return
val pushData = gson.fromJson(jsonData, PushData::class.java)
val channelId = pushData.type?.id ?: DEFAULT_CHANNEL_ID
if (pushData.title.isNullOrBlank() || pushData.body.isNullOrBlank()) {
return
}
val builder = NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(pushData.title)
.setStyle(NotificationCompat.BigTextStyle().bigText(pushData.body))
.setColor(ContextCompat.getColor(context, R.color.push_notification))
.setContentIntent(getPendingIntent(notificationId, pushData))
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
builder.setGroup(DEFAULT_GROUP_KEY)
val groupBuilder = NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_notification)
.setColor(ContextCompat.getColor(context, R.color.push_notification))
.setGroup(DEFAULT_GROUP_KEY)
.setAutoCancel(true)
.setContentIntent(getGroupPendingIntent())
.setGroupSummary(true)
notificationManager.notify(Random.nextInt(0, 1000), builder.build())
notificationManager.notify(DEFAULT_GROUP_KEY.hashCode(), groupBuilder.build())
} else {
notificationManager.notify(Random.nextInt(0, 1000), builder.build())
}
}
private fun createNotificationChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val importance = NotificationManager.IMPORTANCE_HIGH
notificationManager.createNotificationChannels(
PushDataType.values()
.filterNot { it == PushDataType.NONE }
.map { type ->
val name = context.getString(type.nameResId)
val description = context.getString(type.descriptionResId)
NotificationChannel(type.id, name, importance)
.apply {
this.description = description
this.enableVibration(false)
}
}
)
}
}
private fun deleteOldNotificationChannels() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager.deleteNotificationChannel("notification_channel")
}
}
private fun getGroupPendingIntent(): PendingIntent? {
val intent = Intent(context, SplashActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
return PendingIntent.getActivity(
context,
System.currentTimeMillis().toInt(),
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
}
private fun getPendingIntent(notificationId: String?, data: PushData): PendingIntent? {
val intent = Intent(context, SplashActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
intent.putExtra(PUSH_DATA_KEY, data)
intent.putExtra(NOTIFICATION_ID_KEY, notificationId)
return PendingIntent.getActivity(
context,
System.currentTimeMillis().toInt(),
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment