Android NotificationListenerService onNotificationPosted fire twice
Asked Answered
H

6

7

I listen for notifications like WhatsApp Messages.

But every time a notification comes in the NotificationListenerService fire twice.

Does anyone know this problem??

This is a snippet from the AndroidManifest.xml:

<service android:name=".NotifyService"
            android:label="WhatsNotify"
            android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
    <intent-filter>
                <action android:name="android.service.notification.NotificationListenerService"></action>
    </intent-filter>
</service>

And inside the NotificationListenerService class:

public class NotifyService extends NotificationListenerService {

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        Log.i("NotifyService", "got notification");
    }
}

Edit: Properties of both StatusBarNotifications:

First notification:

0|com.whatsapp|1|[email protected]|10073

Second notification:

0|com.whatsapp|1|null|10073

Hadrian answered 29/10, 2015 at 10:46 Comment(7)
have you got this prob's solutionBeamer
@BhanuSharma No. My solution was to create a new android project and then it worked.Hadrian
means same code u wrote in new projects and it will automatically run properly?Beamer
Have u resolved this because i receive this error till dateBeamer
@BhanuSharma I still don't know why I got two notifications. but I created a new project, copied the code from the class file and paste it into the new project. That worked for me.Hadrian
I still got the same problem, the answer below requires API level 20, but I need it to work on level 18.Indo
Your problem is related to group summary notifications. See: https://mcmap.net/q/541371/-android-onnotificationposted-is-called-twice-for-gmail-and-whatsappCellulous
M
5

I'm not sure why this happens. Maybe flags of notifications could be triggering it twice.

You can try to omit duplicate executing yourself:

public class NotifyService extends NotificationListenerService {
    private String mPreviousNotificationKey;
    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        if(TextUtils.isEmpty(mPreviousNotification) || !TextUtils.isEmpty(mPreviousNotification) && !sbn.getKey().equals(mPreviousNotificationKey)){
        Log.i("NotifyService", "got notification");
    }
}

Each StatusBarNotification has unique key which is generated:

private String key() {
   return user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid;

}

Holding each previous key can distinguish latter notification for given package.

Monogamist answered 29/10, 2015 at 11:32 Comment(5)
When the notification the second time fires, all properties are the same like in the first one. Except tag. Tag is null.Hadrian
@Hadrian First one has a tag? What about key property?Monogamist
Yes it has a tag. first time: 0|com.whatsapp|1|[email protected]|10073 second time: 0|com.whatsapp|1|null|10073Hadrian
@Hadrian Try holding reference of the one that has tag, and execute your code when the second one arrives. I don't have any other thoughts about this.Monogamist
Google Allo application coming twice and Tag is null both time what is the answer now ? please helpBeamer
S
2

Facing Same Problem For Whatsapp Notification

I just solve this by generating new key with statusBarNotification.key + statusBarNotification.title

Now store this key in my SQLiteDatabase

code written in Kotlin

 override fun onNotificationPosted(sbn: StatusBarNotification?) {
        if(sbn?.tag!=null) 
        {
        var key = sbn?.key ?: null
        var id = sbn?.id
        var postTime = sbn?.postTime
        var packageName = sbn?.packageName ?: null
        var tikerText = sbn?.notification?.tickerText ?: null

        var extraBundle: Bundle? = sbn?.notification?.extras ?: null
        var notificationTitle = extraBundle?.get(Notification.EXTRA_TITLE)
        var text = extraBundle?.getCharSequence(Notification.EXTRA_TEXT).toString()

        var modifiyedUniq = key + notificationTitle

        //check key present in database or not
        if (!databaseHandler.checkNotification(modifiyedUniq!!)) 
         {
            Log.e(TAG, "Notification Key :: ${key}")
            Log.e(TAG, "Notification Id :: ${id}")
            Log.e(TAG, "Notification postTime :: ${postTime}")
            Log.e(TAG, "Notification From :: ${packageName}")
            Log.e(TAG, "Notification TikerText :: ${tikerText}")
            Log.e(TAG, "Notification Title :: ${notificationTitle}")
            Log.e(TAG, "Notification Text :: ${text}")
            //now add this record in database
            databaseHandler.addNotification(notificationData)
         }
        }
 }

this method databaseHandler.checkNotification(modifiyedUniq!!) returns true if record present with this key else it returns false

each and every time checking the key if no record present means its new notification

fun checkNotification(key: String): Boolean {
    var isPresent: Boolean = false
    val db = readableDatabase
    val selectALLQuery = "SELECT * FROM $TABLE_NAME WHERE $KEY='${key}'"
    val cursor = db.rawQuery(selectALLQuery, null)
    if (cursor != null) {
        if (cursor.count > 0) {
            cursor.close()
            db.close()
            Log.e("","====================================RECORD PRESEBNT=======================")
            return true
        }
    }
    cursor.close()
    db.close()
    Log.e("","===*******=======********=====RECORD NOT PRESENT===*******=======********=====")
    return isPresent
}

Notification 0|com.whatsapp|1|[email protected]|10171

tag = [email protected]

Notification Id :: 1
Notification postTime :: 15464X794103
Notification From :: com.whatsapp
Notification TikerText :: null
Notification Title :: XXX X Bca (2 messages): ​
Notification Text :: XXXXX(last new Message)
Sheaff answered 2/1, 2019 at 7:30 Comment(0)
D
0

This issue happened to me too. My workaround is to use notification's time + (notification's title + notification's text) as two keys.

If time is not older than 1 sec and similar title + text then ignore.

if (Calendar.getInstance().getTimeInMillis() - lastMessageTime < 1000 && lastMessageContent.equalsIgnoreCase(title + text)) {
        // Ignore
        return;
    } else {
        lastMessageContent = title + text;
        lastMessageTime = Calendar.getInstance().getTimeInMillis();
    }

I worked for me but I think it may missed some notification.

Donnie answered 16/7, 2019 at 17:7 Comment(0)
R
0

I found something, the second notification always brings null tag, so this is what I did.

if (sbn.tag != null) {
   // Do something
} else {
   cancelNotification(statusBarNotification.key)
}
Recuperative answered 9/4, 2020 at 23:21 Comment(0)
P
0

I solved it by registering active notification keys like this:

class NotificationsListenerService : NotificationListenerService() {

    private var activeHandledNotificationKeys: MutableSet<String> = mutableSetOf()
        
    override fun onNotificationPosted(sbn: StatusBarNotification) {
        if (activeHandledNotificationKeys.contains(sbn.key)) return
        
        /* Handle unique StatusBarNotification */
        
        activeHandledNotificationKeys.add(sbn.key)
    }
    
    override fun onNotificationRemoved(sbn: StatusBarNotification) {
        activeHandledNotificationKeys.remove(sbn.key)
    }
}
Philbin answered 17/9, 2023 at 14:39 Comment(0)
A
-1

Using Split you can achieve this thing.

 String[] separated = Your Notification key.split("\\|");
    if (!separated[3].equalsIgnoreCase("null")){//Add Your Data in list or DB }
Addam answered 16/5, 2018 at 12:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.