B4A Library NotificationListener library (NotificationListenerService)

Status
Not open for further replies.
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:

SS-2013-12-12_13.06.15.png


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:
SS-2013-12-12_13.08.18.png


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

  • NotificationListener.zip
    6.4 KB · Views: 2,469
  • NotificationListenerExample.zip
    8.7 KB · Views: 1,236
Last edited:

BarryW

Active Member
Licensed User
Longtime 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:

SS-2013-12-12_13.06.15.png


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:
SS-2013-12-12_13.08.18.png


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.

Why I Cant Rename The Service Module... TNX...
 

IzioSettanta

Member
Licensed User
Longtime User
The code you posted in post #49 directly calls an Android API. I don't think that there is a bug in Bundle.getString.

I know but I can't explain how it is possible, the code: no mistakes, no multiply posts, no Android incorrect version....
I think the solution is to parse the string as text with some function. can you help me? do you have any advice?
thank! your developer sofware is amazing!
 

IzioSettanta

Member
Licensed User
Longtime User
I cannot help if you don't exactly answer my questions. I asked you two times to post the output logs and you didn't...

What is the output of:
B4X:
LogColor("text = " & extras.RunMethod("get", Array As Object("android.text")), Colors.Blue)

the output is

text =
 

IzioSettanta

Member
Licensed User
Longtime User
Please post the outputs of these lines:
B4X:
Log(extras)
Log(GetType(extras.RunMethod("get", Array("android.text"))


Log(extras):
B4X:
(Bundle) Bundle[{android.title=IZIO70, android.support.actionExtras={0=Bundle[EMPTY_PARCEL], 1=Bundle[EMPTY_PARCEL]}, [email protected], android.showChronometer=false, android.icon=2130837753, android.text=test message text
, android.progress=0, android.progressMax=0, android.showWhen=true, android.people=[Ljava.lang.String;@42d7eee0, android.largeIcon=android.graphics.Bitmap@42d7f020, android.infoText=null, android.wearable.EXTENSIONS=Bundle[mParcelledData.dataSize=1516], android.progressIndeterminate=false, android.scoreModified=false}]

Log(GetType(extras.RunMethod("get", Array("android.text")):
B4X:
null


but...if you get a text message or whatsapp works. the problem are the emails
 
Last edited:

IzioSettanta

Member
Licensed User
Longtime User
Sorry Erel I made a mistake! the text in the Log(GetType(extras.RunMethod("get", Array("android.text")) now is this: android.text.SpannableString
how can I read it? I can convert it to plain text?
 

IzioSettanta

Member
Licensed User
Longtime User
B4X:
android.text.SpannableString
text = test message
text in text message.

YES!...now work....i think because i use this code to read message text:

B4X:
Private text As String=extras.RunMethod("getString", Array As Object("android.text"))

i use "getString"....instead "get", you use:

B4X:
extras.RunMethod("get", Array("android.text"))

correct?
 

pesquera

Active Member
Licensed User
Longtime User
Hi, the code with intent posted on the first post is very useful to me.. but, I want to do some validations.. is there a way to know if the user has already enabled (or not) my app for accessing to android's notifications?
 

pesquera

Active Member
Licensed User
Longtime User
thanks Erel, sorry for asking something already posted.. and, thanks for give me some light! :)
 

susu

Well-Known Member
Licensed User
Longtime User
Is there anyway NotificationListener stop working? I added this lib and sample code into my project and it worked for about 3 days with alot of tests. However it didn't work again even I try to reinstall my project or copy code from your sample. Now I try to restart my device and hope it will work.
 

susu

Well-Known Member
Licensed User
Longtime User
Ok, after restart my device, this service worked again. It's really weid.
 

susu

Well-Known Member
Licensed User
Longtime User
Now it doesn't work again. Here the logs of error:

B4X:
** Service (notificationservice) Create **
** Service (notificationservice) Start **
notificationservice_listener_notificationremoved (java line: 127)
java.lang.RuntimeException: Object should first be initialized (StatusBarNotification).
    at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:50)
    at anywheresoftware.b4a.objects.NotificationListenerWrapper$StatusBarNotificationWrapper.getPackageName(NotificationListenerWrapper.java:179)
    at v10.noti.notificationservice._listener_notificationremoved(notificationservice.java:127)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
    at anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener.HandleIntent(NotificationListenerWrapper.java:138)
    at v10.noti.notificationservice._service_start(notificationservice.java:160)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
    at v10.noti.notificationservice.handleStart(notificationservice.java:93)
    at v10.noti.notificationservice.onStartCommand(notificationservice.java:68)
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2990)
    at android.app.ActivityThread.access$2100(ActivityThread.java:162)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1446)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5421)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)
notificationservice_service_start (java line: 160)
java.lang.RuntimeException: java.lang.RuntimeException: Object should first be initialized (StatusBarNotification).
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:206)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
    at anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener.HandleIntent(NotificationListenerWrapper.java:138)
    at v10.noti.notificationservice._service_start(notificationservice.java:160)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
    at v10.noti.notificationservice.handleStart(notificationservice.java:93)
    at v10.noti.notificationservice.onStartCommand(notificationservice.java:68)
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2990)
    at android.app.ActivityThread.access$2100(ActivityThread.java:162)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1446)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5421)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)
Caused by: java.lang.RuntimeException: Object should first be initialized (StatusBarNotification).
    at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:50)
    at anywheresoftware.b4a.objects.NotificationListenerWrapper$StatusBarNotificationWrapper.getPackageName(NotificationListenerWrapper.java:179)
    at v10.noti.notificationservice._listener_notificationremoved(notificationservice.java:127)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
    ... 19 more
java.lang.RuntimeException: Unable to start service v10.noti.notificationservice@253c8f05 with Intent { act=b4a_notificationlistener cmp=v10.noti/.notificationservice (has extras) }: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: Object should first be initialized (StatusBarNotification).
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3007)
    at android.app.ActivityThread.access$2100(ActivityThread.java:162)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1446)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5421)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:914)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.RuntimeException: Object should first be initialized (StatusBarNotification).
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:206)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
    at v10.noti.notificationservice.handleStart(notificationservice.java:93)
    at v10.noti.notificationservice.onStartCommand(notificationservice.java:68)
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2990)
    ... 9 more
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: Object should first be initialized (StatusBarNotification).
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:206)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:153)
    at anywheresoftware.b4a.objects.NotificationListenerWrapper$NotificationListener.HandleIntent(NotificationListenerWrapper.java:138)
    at v10.noti.notificationservice._service_start(notificationservice.java:160)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
    ... 13 more
Caused by: java.lang.RuntimeException: Object should first be initialized (StatusBarNotification).
    at anywheresoftware.b4a.AbsObjectWrapper.getObject(AbsObjectWrapper.java:50)
    at anywheresoftware.b4a.objects.NotificationListenerWrapper$StatusBarNotificationWrapper.getPackageName(NotificationListenerWrapper.java:179)
    at v10.noti.notificationservice._listener_notificationremoved(notificationservice.java:127)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
    ... 19 more
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **

Can I manually start NotificationListener? I don't want it run all the time, just when I want to do it.
Thanks.
 

susu

Well-Known Member
Licensed User
Longtime User
B4X:
Sub Listener_NotificationRemoved (SBN As StatusBarNotification)
    If SBN.PackageName = "com.android.server.telecom" Then
        LogColor("Clear Missed Call", Colors.Yellow)
    End If
End Sub

I just want to know when user clear missed call notification to reset timethatcheck = DateTime.Now
CallLog.GetSince(timethatcheck, 0)

Is there anyway to count missed call without browse all CallLog? (like GetUnreadMessages)
 
Status
Not open for further replies.
Top