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|xxxxxxxxxx@s.whatsapp.net|10073

Second notification:

0|com.whatsapp|1|null|10073

Nikola Despotoski
  • 49,966
  • 15
  • 119
  • 148
gravmatt
  • 428
  • 7
  • 17

5 Answers5

6

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.

Nikola Despotoski
  • 49,966
  • 15
  • 119
  • 148
1

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|XX2X606878@s.whatsapp.net|10171

tag = 91XX06X78@s.whatsapp.net

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)
Ashvin solanki
  • 4,802
  • 3
  • 25
  • 65
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.

Khai Nguyen
  • 3,065
  • 1
  • 31
  • 24
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)
}
-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 }
Jeremy Thille
  • 26,047
  • 12
  • 43
  • 63