B4A Library NB6 - Notifications Builder class (2018)

Status
Not open for further replies.

Erel

Administrator
Staff member
Licensed User
Background

For a long time there were two ways for B4A developers to show notifications:
- Simple notifications with the built-in Notification object.
- More complex notifications with barx's NotificationBuilder library. Thank you barx for all your work!!!

The notifications features changed a lot as Android evolved. Android 8 (with targetSdkVersion 26+) adds another complexity with the introduction of notification channels.

The built-in Notification object was rewritten in B4A v8 to work properly with all versions.
This is a good option if you are interested in simple notifications.

I'm less familiar with the internals of barx's NotificationBuilder library and how it works with Android 8+ devices. Example of a simple notification that works on all versions is available here: https://www.b4x.com/android/forum/threads/version-safe-notification.87663/#content

Now for the new option.

NB6 is a class that builds both simple and complex notifications:





It is quite simple to use and the attached example demonstrates most of the features.
NB6 works with all versions of Android, however it focuses on Android 6+ devices. On older devices (Android 5-) it will show a basic notification similar to the one created with the built-in Notification object.

Steps to create a notification:
- Initialize a NB6 object. You need to pass a ChannelId, Channel Name and Importance Level values.
Starting from Android 8+ some of the features are set in the notification channel and not in each notification separately. Once a notification channel is created, it cannot be modified.
If you want to make changes then you need to change the id or uninstall the app (reinstalling is not enough).
NB6 internally adds the importance level string to the channel id. So in most cases you can use the same value for all notifications.
The importance levels are: MIN, LOW, DEFAULT and HIGH.
LOW+ is required for foreground service notifications.
DEFAULT and HIGH enable sounds.
HIGH enables the headup notifications.

- Set the properties. You must set SmallIcon.
- Call Build. The last parameter is the activity that will be started when the user clicks on the notification.
Build returns a notification object.
- Call Notification.Notify to show the notification.

Example:
B4X:
Sub Simple_Notification
   Dim n As NB6
   n.Initialize("default", Application.LabelName, "DEFAULT").AutoCancel(True).SmallIcon(smiley)
   n.Build("Title", "Content", "tag1", Me).Notify(4) 'It will be Main (or any other activity) instead of Me if called from a service.
End Sub

Notes & Tips

- Unlike the built-in Notification object where the icons must be added as resources, NB6 expects bitmaps. This makes it easier to work with NB6.
- Starting from Android 5.1+ the notifications colors are ignored. The transparent parts are used as a mask.
- Don't use the starter service as the target for button actions or delete actions. Use a different service. The starter service cannot be started from a receiver as happens here.
- The notification behavior depends on the launcher. Not all features will work on all devices, even if they run the latest version of Android. 'Not work' means that it will be ignored.
- NB6 is a class module and it uses JavaObject to call the native APIs. The code is quite simple and can be extended.
- The class is included in the attached example. You need to add it to your project and add a reference to the JavaObject library.
- It requires B4A v8+.

Updates

- Version 1.01: Fixes an issue with the channel name always set to Application.LabelName.

Latest version is attached separately.
 

Attachments

Last edited:

Star-Dust

Expert
Licensed User
Thanks, it's really useful. Why do not you make a new library for Notify?
 

Star-Dust

Expert
Licensed User
Why? A Class is better Because you can Change it to Match you needs
I would have agreed if he used native B4A code, because it is very useful for learning.
But many JavaObjects are used and almost like using Java. There is really little to change.

Having a library, the selections and all the new functions are available, instead of loading an external module.
But just my opinion, because I'm lazy and I find it easier to check the checkbox of the library.
 

woniol

Active Member
Licensed User
Hi very cool and waited Class,
but when I run attatched example on Galaxy S5 with Android 6.0.1 i get this error:
B4X:
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
android.app.RemoteServiceException: Bad notification posted from package b4a.example3: Couldn't update icon: StatusBarIcon(icon=Icon(typ=RESOURCE pkg=b4a.example3 id=0x00000000) visible user=0 )
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2019)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:158)
    at android.app.ActivityThread.main(ActivityThread.java:7224)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Any ideas what I do wrong?
 

barx

Well-Known Member
Licensed User
Out of curiousity, was this already in the making before my post with source?
 

Erel

Administrator
Staff member
Licensed User
Thanks, it's really useful. Why do not you make a new library for Notify?
I would have agreed if he used native B4A code, because it is very useful for learning.
But many JavaObjects are used and almost like using Java. There is really little to change.

Having a library, the selections and all the new functions are available, instead of loading an external module.
But just my opinion, because I'm lazy and I find it easier to check the checkbox of the library.
There are only advantages to implementing it as a class:

1. You can compile it to a library if you like. It will not take more than 3 minutes to do it (add #ExcludeFromLibrary: true to MyService and click on Alt + 5).
2. Not that it matters too much but this is 100% B4A code. It is true that it uses JavaObject to directly call native APIs but it is still B4A code.
What is more important is that many developers will be able to extend it as the code is quite simple. This would not have been the case even with an open source Java library.
3. It was easier for me to write it like this.

but when I run attatched example on Galaxy S5 with Android 6.0.1 i get this error:
When does it happen?

Out of curiousity, was this already in the making before my post with source?
Yes.
 
Last edited:

woniol

Active Member
Licensed User
When does it happen?
Mostly when notification from one example is already shown and i run another example.
On some examples like 'Count down notification' or 'Notification with progress' it happes even when previous notifications are not shown.
Looks like some kind of problem with icon update ?
 

asales

Well-Known Member
Licensed User
Very, very nice, but I get this error in "Count down notification" and "Animated notification" too.
I think is the same from @woniol.
B4X:
Activity started from notification. Tag: tag
android.app.RemoteServiceException: Bad notification posted from package b4a.example3.nb6: Couldn't update icon: StatusBarIcon(icon=Icon(typ=RESOURCE pkg=b4a.example3.nb6 id=0x00000000) visible user=0 )
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2046)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:7331)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
It happens in a tablet Galaxy S with Android 6.0.1.
The Big Picture Style don't show the picture too. Same for the Big Text Style.

In a Moto G2 (Android 6.0) and Moto G5 (Android 7.0) it works fine.

In Android 4.0, 4.2 and 4.4 this options (Countdown and Animated) starts like a "loop" and repeat the sound of the notification until finish.
 
Last edited:

PassionDEV

Active Member
Licensed User
On older devices (Android 5-) it will show a basic notification similar to the one
i have tested this library in hope to avoid the ui crash as i mentioned in my other thread
sense the icon should not be loaded if the andriod version is LOLLIPOP but sadly i have got the same problems

icon size 24 x 24 crash UI message in LOLLIPOP 5.1

A blue circle in 5.1.1
 

Erel

Administrator
Staff member
Licensed User
i have tested this library in hope to avoid the ui crash as i mentioned in my other thread
sense the icon should not be loaded if the andriod version is LOLLIPOP but sadly i have got the same problems

icon size 24 x 24 crash UI message in LOLLIPOP 5.1
NB6 uses the built-in Notification object for Android 5- devices. So the behavior will be exactly the same.

In Android 4.0, 4.2 and 4.4 this options (Countdown and Animated) starts like a "loop" and repeat the sound of the notification until finish.
This is expected as these devices do not support the OnlyAlertOnce property, so they make the sound again and again. You should disable the sound with SetDefaults or by changing the importance.

About the "Couldn't update icon" error, it looks like an issue with Galaxy S where it fails to update the notification icon in some cases. You can try to cancel the previous notification (Notification.Cancel) followed by a Sleep of a few hundred milliseconds before showing the notification again. Make sure to disable sound.
It might help.
 

woniol

Active Member
Licensed User
About the "Couldn't update icon" error, it looks like an issue with Galaxy S where it fails to update the notification icon in some cases. You can try to cancel the previous notification (Notification.Cancel) followed by a Sleep of a few hundred milliseconds before showing the notification again. Make sure to disable sound.
It might help.
It does help, but doesn't look nice with all kinds of notification from the examples.
 

woniol

Active Member
Licensed User
As I wrote, it looks like a problem in that specific device.
I works fine when I changed CreateIconFromBitmap method, so that the icon i created with createWithResource instead of createWithBitmap
example:
B4X:
Private Sub CreateIconFromBitmap(bmp As Bitmap) As Object
    If bmp = Null Or bmp.IsInitialized = False Then Return 0
    Dim icon As JavaObject
    'Return icon.InitializeStatic("android.graphics.drawable.Icon").RunMethod("createWithBitmap", Array(bmp))
    Dim xml As XmlLayoutBuilder
    Return icon.InitializeStatic("android.graphics.drawable.Icon").RunMethod("createWithResource", Array(ctxt,xml.GetResourceId("drawable","icon")))
 

walterf25

Expert
Licensed User
Hi All, i started using this class and it works great Thank you @Erel, however i'm having an issue where i receive two notifications when i send a notification, i'am using a service which builds the notification and displays it when ready, the problem is that if the app is active meaning opened, i only receive 1 notification and i see a number 1 badge on the app's icon, but if the app is closed i receive two notifications and i see a number 2 badge on the app's icon, i'm able to clear the notification that contains the message but the second notification stays and i can't seem to clear it or make it go away.

Here's my code.
B4X:
Sub BigText_Notification(title As String, message As String)
    Dim n As NB6
    n.Initialize("default", Application.LabelName, "HIGH").SmallIcon(icon)
    Dim cs As CSBuilder
    ''n.BigPictureStyle(icon.Resize(256dip, 256dip, True), icon, title, message)
    n.BigTextStyle(title, cs.Initialize.BackgroundColor(Colors.Green).Append("Message Summary").PopAll, message)
    Dim cur1 As Cursor
    cur1 = Common.SQL1.ExecQuery("SELECT * FROM registration")
    cur1.Position = 0
        
    'check if user is registered to a group, otherwise register to group by
    'getting groupregistered flag in notification message.
    Dim groupregistered As Int
    Try
    groupregistered = cur1.GetInt("groupregistered")
    If groupregistered <> 0 Then
    n.Build(title, "Read Content Below", "notification_alert", CustomMessages).Notify(1)
    Else
    n.Build(title, "Read Content Below", "notification_alert", Main).Notify(1)
    End If
    Catch
    n.Build(title, "Read Content Below", "notification_alert", Main).Notify(1)
    End Try
End Sub
Attached is also a picture of what i'm seeing, the top is the notification that can be cleared, the bottom one can't be cleared at all, why am i receiving two notifications when the app is closed or not Active.

Thanks all.
WalterScreenshot_20180418-230416_Samsung Experience Home.jpg
 
Status
Not open for further replies.
Top