How to send a request when push notification is cancelled in Android

本小妞迷上赌 提交于 2021-02-18 19:21:32

问题


When an application receives push notification from FCM, it calls onMessageReceived. (See 1, 2 or 3.)

When a user taps the notification, it launches the applications, then it sends a request to a server that the user has read the notification.

I want to know when a device received a push notification, but the user swiped it (or cleared all notifications). I want to send a request to the server that the user simply cancelled the notification.

I tried to send BroadcastReceiver and show logs (see 4 or 5), but it works when the application was opened when the notification delivered. I suppose, that

MyFirebaseMessagingService:

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    ...
    // An event when a user swipes a notification.
    val intent = Intent(this, NotificationBroadcastReceiver::class.java)
    intent.action = "notification_cancelled"
    val deleteIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)
    notificationBuilder.setDeleteIntent(deleteIntent)

    // Navigation to an activity when a user taps the notification.
    // It doesn't matter to this question.
    val intent2 = Intent(this, MainActivity::class.java)
    val navigateIntent = PendingIntent.getActivity(this, notificationId, intent2,
        PendingIntent.FLAG_UPDATE_CURRENT)
    notificationBuilder.setContentIntent(navigateIntent)
    ...
}

NotificationBroadcastReceiver:

class NotificationBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        Timber.d("NotificationBroadcastReceiver onReceive")
        Toast.makeText(context, "Notification dismissed", Toast.LENGTH_LONG).show()
        // Send a request to the server.
    }
}

AndroidManifest:

<uses-permission android:name="com.uremont.NOTIFICATION_PERMISSION" />

    <receiver
        android:name=".receiver.NotificationBroadcastReceiver"
        android:exported="true"
        android:permission="NOTIFICATION_PERMISSION"
        >
        <intent-filter>
            <action android:name="notification_cancelled" />
        </intent-filter>
    </receiver>

works only when the application is opened. But when the application is in background or killed, it doesn't react to swipe. Probably we shouldn't use BroadcastReceiver, for instance, use PendingIntent.getService or PendingIntent.getForegroundService.

Can we send a request to the server?


回答1:


After a short time it worked right (though I hardly changed much). After a lot of research I made this solution. Tested on several Android emulators and devices from API 19 to API 30.

Because using BroadcastReceiver is not safe, add in AndroidManifest:

<receiver
    android:name=".NotificationBroadcastReceiver"
    android:exported="false"
    />

NotificationBroadcastReceiver:

class NotificationBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        Timber.d("NotificationBroadcastReceiver onReceive")

        if (intent.extras != null) {
            // Receive parameters of a cancelled notification.
            val authToken = intent.getStringExtra(EXTRA_TOKEN)
            val code = intent.getStringExtra(EXTRA_CODE)
            Timber.d("token = $authToken, code = $code")
            // We can access context even if the application was removed from the recent list.
            Toast.makeText(context, "Notification $code was cancelled", Toast.LENGTH_SHORT).show()
            // Send data to a server.
        }
    }

    companion object {
        const val EXTRA_TOKEN = "EXTRA_TOKEN"
        const val EXTRA_CODE = "EXTRA_CODE"
    }
}

MyFirebaseMessagingService:

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    ...
    // Get notification code from data.
    val code = remoteMessage.data["code"]

    val notificationBuilder = NotificationCompat.Builder(this,
    ...

    val notificationId = Random.nextInt()
    val intent = Intent(this, NotificationBroadcastReceiver::class.java).apply {
        putExtra(EXTRA_TOKEN, authToken)
        putExtra(EXTRA_CODE, code)
    }
    val deleteIntent = PendingIntent.getBroadcast(this, notificationId, intent,
        PendingIntent.FLAG_CANCEL_CURRENT)
    notificationBuilder.setDeleteIntent(deleteIntent)

    val notification = notificationBuilder.build()
    notificationManager.notify(notificationId, notification)
}

Send a push message to Android device with it's push token, for instance:

{
  "to": "ddSOGiz4QzmY.....:APA91bHgoincFw.......",
  "data": {
    "title": "Test",
    "message": "Test",
    "code": "ABCDEF"
  }
}

You can see different schemes of delivering push messages here. If a user presses "Force stop" at the application, it won't receive push messages (except "AliExpress", ha-ha).

When the user dismisses push notification, NotificationBroadcastReceiver::onReceive() is called. An application gets parameters of the push message. Then we can see a toast message and send these parameters to the server.

When the user presses "Clear all" notifications, all dismiss events are fired. So, you will see a sequence of toasts. The server will receive several requests simultaneously (check that it can handle, for instance, 10 requests in 0.01 second).



来源:https://stackoverflow.com/questions/65703474/how-to-send-a-request-when-push-notification-is-cancelled-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!