I am trying to get a similar behavior with remote push notifications on the Android version of my app as I have in my iOS version. In iOS, when a notification arrives it shows a heads up message regardless of the state of the app or the device (more or less...) If the app is in the foreground, background, or screen turned off - it always shows a message. But in Android, I haven't been able to find a solution that works when the device screen is turned off. So my question is, how can I make a remote notification turn on the screen and show the notification as a heads up message?
I have the following implementation of the FirebaseMessagingService
.
class NotificationService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
remoteMessage.data.let {
it["body"]?.let { body -> sendNotification(body) }
}
}
private fun sendNotification(messageBody: String) {
val channelId = getString(R.string.default_notification_channel_id)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val requestCode = 0
val fullScreenIntent = Intent(this, MainActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(
this,
requestCode,
fullScreenIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId,
"My Channel",
NotificationManager.IMPORTANCE_HIGH,
)
channel.description = "Notifications."
channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
channel.enableVibration(true)
channel.vibrationPattern = longArrayOf(200, 200, 200, 200, 200)
notificationManager.createNotificationChannel(channel)
}
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notificationBuilder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.alert_title))
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setDefaults(NotificationCompat.DEFAULT_VIBRATE)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setOnlyAlertOnce(true)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setFullScreenIntent(fullScreenPendingIntent, true)
val notificationId = 0
notificationManager.notify(notificationId, notificationBuilder.build())
}
}
I have these permissions in my manifest.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
As well as the messaging service.
<service
android:name=".NotificationService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
This works fine and shows a heads-up message when the app is in the foreground or background, but not on a locked / turned off screen. I have seen solutions like this one.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
this.setTurnScreenOn(true);
} else {
final Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
But since I am passing the fullScreenIntent
directly to the notificationBuilder
, I'm not sure where to add this code (Kotlin equivalent of course). It seems that it should belong to the specific Activity
of the heads-up message. But how can I access that?
Alternatively, I guess I could build a custom notification with it's own Activity
, but then I'm not sure how to pass the data from the notification to it. And I would rather use the default notification layout than have to make a custom one.
I hope there is a more straightforward way of solving this, preferably a simple method on the builder. I noticed that there is a setPublicVersion()
method, but I'm not sure if this is applicable here or how I would implement this.
Any suggestions / solutions are most welcome! Cheers!