B4A Library NotificationListener library (NotificationListenerService)

Status
Not open for further replies.

Erel

Administrator
Staff member
Licensed User
The NotificationListener library allows you to access the device notifications. This is a new feature which is only available on Android 4.3+ (api 18+).

With this library you can listen to new notifications and removed notifications.

You can also clear existing notifications.

There are some steps that you need to follow in order to use this feature:
- Make sure that the IDE references android.jar from API level 18+.
- Download the attached library and copy it to the libraries folder.
- Add a Service module named NotificationService (must be this exact name).
- Add the following code to the manifest editor:
B4X:
AddApplicationText(
<service android:name="anywheresoftware.b4a.objects.NotificationListenerWrapper"
   android:label="Notification Listener"
  android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
  <intent-filter>
  <action android:name="android.service.notification.NotificationListenerService" />
  </intent-filter>
</service>)
You can change the value of android:label.

- The user must enable your app before it can listen to notifications. This is done by sending the following intent:
B4X:
Sub btnEnableNotifications_Click
   Dim In As Intent
   In.Initialize("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS", "")
   StartActivity(In)
End Sub
The user will see the following screen:



In the service you should create a NotificationListener object and let it handle the StartingIntent:
B4X:
Sub Process_Globals
   Private listener As NotificationListener
End Sub
Sub Service_Create
   listener.Initialize("listener")
End Sub

Sub Service_Start (StartingIntent As Intent)
   If listener.HandleIntent(StartingIntent) Then Return
End Sub
The following events will be raised: NotificationPosted and NotificationRemoved.

See the attached example. It extracts data out of the notifications and print it to the logs:


Note that only in Android 4.4 you can extract the title and other values (extracted with JavaObject).

Tips

- The notifications will also be handled when your app is not running. The service will first be created.
- There is no way to check whether the app is enabled or not.
- If your service is configured incorrectly when you enable the app then nothing will work and there will be no error message. Even after you reinstall the app. In that case you should either change the app package name or restart the device.
- You can also reach the settings screen by going to Settings > Security > Notification Access.
 

Attachments

Last edited:

AirLink

Member
Licensed User
Hi Erel!
Thanks for the library!

I was trying to have some custom alerts based on the received notifications however not all notifications trigger the NotificationPosted event. Any clue why this is happening? SMS / Missed call & B4A created notifications al trigger the event fine but Gmail, Hangouts, WhatsApp and others do not. They all trigger the NotificationRemoved event just fine whether removed by hand or by calling listener.ClearAll

Any chance you could extend this with a getActiveNotifications method ?

Tested the example on Android 4.3

Thank you!
 

Erel

Administrator
Staff member
Licensed User
V1.1 uploaded. Fixes the missing notifications issue and adds a GetActiveNotifications method.
 

AirLink

Member
Licensed User
I just tested the new version and all works great now!
Thank you for the very fast update! :)
 

bgsoft

Well-Known Member
Licensed User
Hello

I can enable / disable the setting screen by code (attached image setting.jpg)?


I can make the message displayed when the notification is triggered not appear (attached image message.jpg)?

thanks
 

Attachments

Erel

Administrator
Staff member
Licensed User
No. You cannot enable it programmatically. This is a security feature.

You can open the settings page as explained in the first post.
 

bluedude

Well-Known Member
Licensed User
This worked in B4A 2.7 but in 3.5 I get:

Caused by: java.lang.RuntimeException: java.lang.Exception: Sub service_create signature does not match expected signature.

Not sure what that is. Service_Start looks good.

Sub Service_Start (StartingIntent As Intent)
If listener.HandleIntent(StartingIntent) Then Return
End Sub
 

Erel

Administrator
Staff member
Licensed User
Can you post the full error message? Does it happen in Release mode as well?
 

frapel

Active Member
Licensed User

Erel

Administrator
Staff member
Licensed User
AccessibilityManager can only be used when implementing an accessibility service app. It cannot be added to regular apps.
 

NeoTechni

Well-Known Member
Licensed User
I noticed these extras:
android.icon = 2130837725
android.largeIcon=android.graphics.Bitmap@4301a330

How can we get the images?

EDIT: I remembered I asked a similar question before, and you replied with
B4X:
Dim r As Reflector
r.Target = StartingIntent
Dim bmp As Bitmap = r.RunMethod2("getParcelableExtra", <key>, "java.lang.String")
that should get the largeicon, how do I get the small one?

EDIT 2:
java.lang.NoSuchMethodException: getParcelableExtra [class java.lang.String]
Dang.
 
Last edited:

NeoTechni

Well-Known Member
Licensed User
As a note, since the properties of a statusbarnotification are write-only for some reason, I had to make a surrogate type to store all the data in
And I don't even have access to some properties like if it's persistent or not (which would mean I don't have to re-enumerate the notifications after clearing them, if I just erase the non-persistent ones) And I can't seem to filter out null strings for some reason.

B4X:
Sub Process_Globals
   Private listener As NotificationListener
   Type NOTI(id As Long, PackageName As String, TickerText As String, title As String, subText As String, showChronometer As Boolean, icon As Long, text As String, textLines As String, progress As Int, progressMax As Int, showWhen As Boolean, largeIcon As Bitmap, infoText As String, progressIndeterminate As Boolean, scoreModified As Boolean )
   Dim SDKversion As Int, Notifications As List
End Sub


Sub Listener_NotificationPosted (SBN As StatusBarNotification)
   Notifications.Add(SBNSurrogate(SBN))
   'Log("NotificationPosted, package = " & SBN.PackageName & ", id = " & SBN.Id & ", text = " & SBN.TickerText)
End Sub


Sub SBNSurrogate(SBN As StatusBarNotification) As NOTI
   Dim temp As NOTI, Extras As JavaObject = GetExtras(SBN)
   temp.Initialize
   temp.id = SBN.id
   temp.PackageName=SBN.PackageName
   temp.TickerText= SBN.TickerText
   
   temp.title  = GetExtra(Extras, "title")
   temp.subText = GetExtra(Extras, "subText")
   temp.showChronometer = GetBoolean(Extras, "showChronometer")
   temp.icon = GetDouble(Extras, "icon")
   temp.text = GetExtra(Extras, "text")
   
   temp.textLines = GetExtra(Extras, "textLines")
   temp.progress = GetDouble(Extras, "progress")
   temp.progressMax = GetDouble(Extras, "progressMax")
   temp.showWhen = GetBoolean(Extras, "showWhen")
   temp.infoText = GetExtra(Extras, "infoText")
   temp.progressIndeterminate = GetBoolean(Extras, "progressIndeterminate")
   temp.scoreModified = GetBoolean(Extras, "scoreModified")
   
   'temp.largeIcon = GetLargeIcon(Extras)
   Log("NOTI: " & temp)
   Return temp
End Sub

Public Sub GetExtras(SBN As StatusBarNotification) As JavaObject
   If SDKversion >= 19 AND SBN.IsInitialized Then
     Dim jno As JavaObject = SBN.Notification
     If jno.IsInitialized Then
       Dim Extras As JavaObject = jno.GetField("extras")
       Extras.RunMethod("size", Null)
       Return Extras
     End If
   End If
End Sub

'Available extras: title, subText, showChronometer(bool), icon(long), text textLines progress(int) progressMax(int) showWhen(bool) largeIcon(bmp) infoText progressIndeterminate(bool) scoreModified(bool)
Public Sub GetExtra(Extras As JavaObject, Name As String) As String
   Return Extras.RunMethod("getString", Array As Object("android." & Name))
End Sub

Public Sub GetString(Extras As JavaObject, Name As String) As String
   Dim temp As String = GetExtra(Extras, Name)
   If temp = Null Then Return "" 'Isn't working for some reason, I still get null strings
   Return temp
End Sub
Public Sub GetBoolean(Extras As JavaObject, Name As String) As Boolean
   Dim temp As String = GetExtra(Extras, Name)
   Return temp.ToLowerCase = "true"
End Sub
Public Sub GetDouble(Extras As JavaObject, Name As String) As Long
   Return Extras.RunMethod("getInt", Array As Object("android." & Name))
End Sub

Public Sub GetLargeIcon(Extras As JavaObject) As Bitmap
   Dim r As Reflector, temp As Bitmap 'doesn't work yet
   r.Target = Extras
   temp = r.RunMethod2("getParcelableExtra", "android.largeIcon", "java.lang.String")
   Return temp
End Sub
 

Erel

Administrator
Staff member
Licensed User
This code will extract the bitmap from the notification:
B4X:
Dim bmp As Bitmap = jno.GetField("largeIcon")
 

MrKim

Well-Known Member
Licensed User
Question: I have an app that is listens for SMS messages:
B4X:
AddReceiverText(DoSMSNotification, <intent-filter>    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>)
Unfortunately some very popular applications evidently intercept this message before me and my app fails.
Will this solve this problem?

Thanks
Kim
 

Erel

Administrator
Staff member
Licensed User
This library allows you to intercept notifications. Whether it will solve your app requirements or not depends on your specific requirements.
 
Status
Not open for further replies.
Top