Search code examples
androidfirebase-cloud-messaginglockscreen

Android 11 FCM problem on locked screen (Kotlin)


I have an application. I extended the FirebaseMessagingServie. I added it into the manifest:

        <service
        android:name=".services.AutomentoFirebaseMessagingService"
        android:directBootAware="true"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

I also overided the onMessageRecived method

 override fun onMessageReceived(remoteMessage: RemoteMessage) {
    Log.d(TAG, "Topic message: " + remoteMessage.from)
    super.onMessageReceived(remoteMessage)

    val powerIntent = Intent(Intent.ACTION_POWER_CONNECTED)
    context?.sendBroadcast(powerIntent)

    wakeUpScreen()

    val intent = Intent(this, MainActivity::class.java)
    val pendingIntent = PendingIntent.getActivity(
        this,
        REQUEST_CODE, intent, PendingIntent.FLAG_ONE_SHOT
    )
    val channelId = getString(R.string.default_notification_channel_id)
    val notificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(this, channelId)
        .setSmallIcon(R.drawable.ic_rendeleseim_white_48)
        .setContentTitle(remoteMessage.notification!!.title)
        .setContentText(remoteMessage.notification!!.body)
        .setAutoCancel(true)
        .setContentIntent(pendingIntent)
        .setOngoing(true)
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .setLights(Color.RED, 500, 500)
    val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager

    val channel = NotificationChannel(
        channelId,
        "Pushnotification",
        NotificationManager.IMPORTANCE_HIGH,
    ).apply {
        lockscreenVisibility = Notification.VISIBILITY_PUBLIC
    }
    
    notificationManager.createNotificationChannel(channel)
    val notification = notificationBuilder.build()
    notification.flags = notification.flags or Notification.FLAG_INSISTENT
    notificationManager.notify(REQUEST_CODE, notification)
}

private fun wakeUpScreen() {
    val powerManager = getSystemService(POWER_SERVICE) as PowerManager
    val isScreenOn: Boolean = powerManager.isInteractive
    if (!isScreenOn) {
        val wakeLock: PowerManager.WakeLock =
            (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
                newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MentoMano::WakelockTag").apply {
                    acquire(1000)
                }
            }
    }

    val pm = context!!.getSystemService(POWER_SERVICE) as PowerManager
    val isScreenOn2 = pm.isInteractive // check if screen is on

    if (!isScreenOn2) {
        val wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP, "myApp:notificationLock")
        wl.acquire(3000) //set your time in milliseconds
    }
}

I have the API key and I get the token. I can send a notification and the user get it when the app is runing, when it is in the background and it is not running.

My problem: the user doesn't get the notification when the screen is locked. I configured the phone. I can get pushnotification from the facebook Messenger when the phone is locked, but my notification arrives only when the user opens the screen or the screen is opened.


Solution

  • If it helps somebodey I used this solution.

    I kept the manifest as in the question

    In inherited from FirebaseMessagingService

    class MyMessagingService: FirebaseMessagingService {
    

    And I used this onMessageRecibed function

     override fun onMessageReceived(remoteMessage: RemoteMessage) {
            Log.d(TAG, "Topic message: " + remoteMessage.from)
            super.onMessageReceived(remoteMessage)
    
            val powerIntent = Intent(Intent.ACTION_POWER_CONNECTED)
            context?.sendBroadcast(powerIntent)
    
            wakeUpScreen()
    
            val intent = Intent(this, MainActivity::class.java)
            val pendingIntent = PendingIntent.getActivity(
                this,
                REQUEST_CODE,
                intent,
                PendingIntent.FLAG_IMMUTABLE
            )
            val channelId = getString(R.string.default_notification_channel_id)
            val notificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(this, channelId)
                .setSmallIcon(R.drawable.ic_rendeleseim_white_48)
                .setContentTitle(remoteMessage.notification!!.title)
                .setContentText(remoteMessage.notification!!.body)
                .setAutoCancel(true)
                .setContentIntent(pendingIntent)
                .setOngoing(true)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setLights(Color.RED, 500, 500)
            val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
    
            val channel = NotificationChannel(
                channelId,
                "Pushnotification",
                NotificationManager.IMPORTANCE_HIGH,
            ).apply {
                lockscreenVisibility = Notification.VISIBILITY_PUBLIC
            }
    
            notificationManager.createNotificationChannel(channel)
            val notification = notificationBuilder.build()
            notification.flags = notification.flags or Notification.FLAG_INSISTENT
            notificationManager.notify(REQUEST_CODE, notification)
        }
    

    This is the wakeUpScreen method

      private fun wakeUpScreen() {
            val powerManager = getSystemService(POWER_SERVICE) as PowerManager
            val isScreenOn: Boolean = powerManager.isInteractive
            if (!isScreenOn) {
                val wakeLock: PowerManager.WakeLock =
                    (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
                        newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MentoMano::WakelockTag").apply {
                            acquire(1000)
                        }
                    }
            }
    
            val pm = baseContext.getSystemService(POWER_SERVICE) as PowerManager
            val isScreenOn2 = pm.isInteractive // check if screen is on
    
            if (!isScreenOn2) {
                val wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP, "myApp:notificationLock")
                wl.acquire(3000) //set your time in milliseconds
            }
        }