Android Question Notification Listener from "Example of #Extends in Service"

wes58

Active Member
Licensed User
I have been trying to use #Extends Attribute, and I found this thread with Notification Listener library https://www.b4x.com/android/forum/threads/example-of-extends-in-service.74880/#content
I added to the example a code to clear one notification:
B4X:
Sub Clear(sbn As StatusBarNotification)
    listener.ClearNotification(sbn)
End Sub
Where sbn is a StatusBarNotification received in sub Listener_NotificationPosted(SBN As StatusBarNotification)
When I try to clear one notification, I get this error:
B4X:
notificationservice_clear (java line: 130)
java.lang.RuntimeException: java.lang.IllegalArgumentException: Expected receiver of type android.service.notification.NotificationListenerService, but got anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener
    at anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener.ClearNotification(NotificationListenerWrapper.java:90)
    at b4a.notificationlistener.notificationservice._clear(notificationservice.java:130)
It's probably a question for Erel, since he made this library for this example. But anyone is welcome with any suggestions.
 

wes58

Active Member
Licensed User
Is this the full error message?
I though that this is the most important part.
But here is the full message.
B4X:
notificationservice_clear (java line: 130)
java.lang.RuntimeException: java.lang.IllegalArgumentException: Expected receiver of type android.service.notification.NotificationListenerService, but got anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener
    at anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener.ClearNotification(NotificationListenerWrapper.java:84)
    at b4a.notificationlistener.notificationservice._clear(notificationservice.java:130)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:196)
    at anywheresoftware.b4a.keywords.Common$11.run(Common.java:1179)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7032)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
Caused by: java.lang.IllegalArgumentException: Expected receiver of type android.service.notification.NotificationListenerService, but got anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener.ClearNotification(NotificationListenerWrapper.java:82)
    ... 11 more
And here is the code just for testing, that calls the sub in the Notificationservice:
sbnlist is a List to which sbn notifications posted are added to in the Listener_NotificationPosted sub
B4X:
Sub btnClear_Click
    Dim i As Int
    Dim j As Int
    j = EditText1.Text
    Log("size " & sbnlist.Size)
    If sbnlist.Size > 0 Then
        For i = 0 To sbnlist.Size-1
            Dim sbn As StatusBarNotification
            sbn = sbnlist.Get(i)
            Log("i " & i & " j " & j & " sbnid " & sbn.Id & " " & sbn.PackageName)
            If j = sbn.Id Then
                CallSubDelayed2(NotificationService, "Clear", sbn)
                Exit
            End If
        Next
    End If
End Sub
 
Last edited:

wes58

Active Member
Licensed User
Is there any advantage of clearing the way you do in your java library - i.e. ClearNotification(sbn), instead of clearing by an sbn.id like this?
B4X:
    /**
     * clear one notification with ID
     */
    public  void  ClearNotificationID(int id){
            Context context = BA.applicationContext;
            NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.cancel(id);
    }
This code works.

I still would like to know how to fix this error, if possible.
 

wes58

Active Member
Licensed User
What is the output of:
B4X:
Sub Clear(sbn As StatusBarNotification)
    Log(sbn)
    Log(GetType(sbn))
    listener.ClearNotification(sbn)
End Sub
Here it is:
B4X:
sbn = (StatusBarNotification) StatusBarNotification(pkg=b4a.notificationlistener user=UserHandle{0} id=5 tag=null key=0|b4a.notificationlistener|5|null|10385: Notification(channel=channel_3 pri=0 contentView=null vibrate=default sound=default defaults=0xffffffff flags=0x0 color=0x00000000 vis=PRIVATE semFlags=0x0 semPriority=0 semMissedCount=0))
GetType(sbn) = android.service.notification.StatusBarNotification
notificationservice_clear (java line: 134)
java.lang.RuntimeException: java.lang.IllegalArgumentException: Expected receiver of type android.service.notification.NotificationListenerService, but got anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener
    at anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener.ClearNotification(NotificationListenerWrapper.java:84)
    at b4a.notificationlistener.notificationservice._clear(notificationservice.java:134)
    at java.lang.reflect.Method.invoke(Native Method)
 

wes58

Active Member
Licensed User
Since I didn't get a solution and the method of clearing the notification that I posted in post #4, only allows you to clear your own notifications I had to find the solution to the bug in the library posted in https://www.b4x.com/android/forum/threads/example-of-extends-in-service.74880/#content myself.
Unfortunately to do it I had to decompile the library to see the source code. The function to clear notification - public void ClearNotification(StatusBarNotificationWrapper SBN) - is located in NotificationListener class.
The function is like this:
B4X:
public void ClearNotification(StatusBarNotificationWrapper SBN) {
        StatusBarNotification sbn = (StatusBarNotification) SBN.getObject();
        if (VERSION.SDK_INT >= 21) {
            try {
                String key = (String) sbn.getClass().getMethod("getKey").invoke(sbn);
                this.owner.getClass().getMethod("cancelNotification", String.class).invoke(this, key);
            } catch (Exception var4) {
                throw new RuntimeException(var4);
            }
        } else {
            this.owner.cancelNotification(sbn.getPackageName(), sbn.getTag(), sbn.getId());
        }

    }
The error message indicated RuntimeException that occurred in try-catch.
This meant that the problem was, that this function should be in NotificationListenerWrapper extends NotificationListenerService class.
So to fix it, I put in NotificationListenerWrapper extends NotificationListenerService class, function
B4X:
public void ClearNotification(StatusBarNotification SBN) {                             //changed from StatusBarNotificationWrapper to StatusBarNotification
        StatusBarNotification sbn = (StatusBarNotification) SBN.getObject();
        if (VERSION.SDK_INT >= 21) {
            try {
                String key = (String) sbn.getClass().getMethod("getKey").invoke(sbn);
                this.getClass().getMethod("cancelNotification", String.class).invoke(this, key);
            } catch (Exception var4) {
                throw new RuntimeException(var4);
            }
        } else {
            this.cancelNotification(sbn.getPackageName(), sbn.getTag(), sbn.getId());
        }

    }
and in NotificationListener class function:
B4X:
public void ClearNotification(StatusBarNotificationWrapper SBN) {
        StatusBarNotification sbn = (StatusBarNotification) SBN.getObject();
        owner.ClearNotification(SBN);
    }
That's it.
 
Last edited:
Top