Android Question How to start another activity when Replacing Notification by NB6

Alain75

Member
I used the simple notification builder and passed an intent in the setinfo2 activity parameter in order to start another application when clicking the notification.

SetInfo2 of Notification:
dim notif as Notification, pm as PackageManager
...
notif.SetInfo2("Title","Text","",pm.GetApplicationIntent(xxx))

I want to switch to NB6 because It would be great to show the icon of the other application with the LargeIcon. I thaught that NB6 will react as Notification when passing the intent in the activity parameter of the build method.

Build of NB6:
dim notif as NB6, pm as PackageManager
...
notif.Build("Title","Text","",pm.GetApplicationIntent(xxx))

Unfortunately, it crashs with error :
B4X:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Class.getName()' on a null object reference

I tried the same approach passing intent in activity parameter of method AddButtonAction2 but with more or less he same problem...

Instead of Me, what should be the activity parameter to launch another application from the notification click ?
Thanks
 

Alain75

Member
Sorry, I forgot to precise that I don't use B4XPage. However, it means that I must start again my application and give in the tag the other application to launch ? It is not really pretty. With the simple notification, the click launchs directly the other application...
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Upvote 0

Alain75

Member
Sorry but even if it should work, it doesn't with NB6 object whereas it runs with Notification object. And yet I pass strictly the same object (pm.getApplicationIntent(...))but I get :
B4X:
nb6_createintent (java line: 301)
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Class.getName()' on a null object reference
    at android.content.ComponentName.<init>(ComponentName.java:132)
    at android.content.Intent.<init>(Intent.java:7489)
    at java.lang.reflect.Constructor.newInstance0(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
    at anywheresoftware.b4j.object.JavaObject.InitializeNewInstance(JavaObject.java:91)
    at b4a.crnotifs.nb6._createintent(nb6.java:301)
    at b4a.crnotifs.nb6._build(nb6.java:189)
    at b4a.crnotifs.tools._notification3(tools.java:1203)
    at b4a.crnotifs.main._notifier(main.java:1197)
    at b4a.crnotifs.main$ResumableSub_NOTIF_Click.resume(main.java:1134)
    at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:275)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:215)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at anywheresoftware.b4a.keywords.Common$15.run(Common.java:1804)
    at android.os.Handler.handleCallback(Handler.java:938)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:246)
    at android.app.ActivityThread.main(ActivityThread.java:8653)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
 
Upvote 0

teddybear

Well-Known Member
Licensed User
As Erel said at post#2 you should pass the activity instead of the intent.

Sampe is attached
 

Attachments

  • Notif.zip
    15.6 KB · Views: 164
Upvote 0

Alain75

Member
I think you misunderstand my problem. With Notification object, the click on the notification launches Chrome in a new independant activity and is not launched through an activity of my app...
 
Upvote 0

Alain75

Member
I understood that if Notification object is able to add a tag in the activity passed as a parameter, the NB6 object as no ability to add one in its build method. I looked deeply in NB6 code and think that a fix could be like that when the activity passed is an intent :
Possible fix ???:
Public Sub Build (ContentTitle As Object, ContentText As Object, Tag As String, Activity As Object) As Notification
    If IsOld Then
        OldNotification.SetInfo2(ContentTitle, ContentText, Tag, Activity)
        Return OldNotification
    Else
        Dim in As Intent = CreateIntent(Activity, False)
        in.Flags = Bit.Or(268435456, 131072) 'FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_REORDER_TO_FRONT
        in.PutExtra("Notification_Tag", Tag)
        If Activity is Intent Then
            Dim pm As PackageManager,pakage as String, class As String
            package = Activity.As(JavaObject).RunMethod("getComponent",Null).As(JavaObject).RunMethod("getPackageName",Null)
            class = Activity.As(JavaObject).RunMethod("getComponent",Null).As(JavaObject).RunMethod("getClassName",Null)
            in.SetComponent(package&"/"&class)     
        End If
        Dim PendingIntent As Object = PendingIntentStatic.RunMethod("getActivity", Array(ctxt, Rnd(0, 0x7fffffff), in, GetPendingIntentFlag))
        NotificationBuilder.RunMethodJO("setContentTitle", Array(ContentTitle)).RunMethodJO("setContentText", Array(ContentText))
        NotificationBuilder.RunMethod("setContentIntent", Array(PendingIntent)
        If IsChannel Then
            Dim manager As JavaObject = ctxt.RunMethod("getSystemService", Array("notification"))
            manager.RunMethod("createNotificationChannel", Array(Channel))
        End If
        Return NotificationBuilder.RunMethod("build", Null)
    End If
End Sub
and the notification will launch directly the application :)

Of course, my code is not pretty, might be better written and also integrated in addButtonAction2
 
Upvote 0

Alain75

Member
I am sorry that you don't understand my problem 😞. But using NB6 and passing an intent in Activity parameter of the build method crashs with the error previously reported. One of my friends developping with B4A has confirmed this bug.

So, I finally wrote my own simplified "NB6 Notification" using "DEFAULT" ChannelId, based on your b4xlib and it works. When the Activity parameter is :
  • Me, the click on the notification restarts the current activity,
  • An "empty" intent, that is just an intent initialized, the click on the notification does nothing except canceling the notification (with AutoCancel set as is of course),
  • A "standard" intent, the click on the notification launchs directly the corresponding application without passing through my application.
Moreover, the management of the tag has been enhanced :
  • By default, it writes the "Notification_tag".
  • But if the string corresponds to the form "extra1=value1;extra2=value2;..." it writes as many extra fields as values found.
Below is the code really hopping that you understand the problem I encountered :
B4X:
Sub NB6Notification(Id As Int,xTitle As Object,xTexte As Object,Number As Object,xTag As String,Pkg As String,xActivity As Object)
    Dim  ctxt, NBuilder As JavaObject, pm As PackageManager
    ctxt.InitializeContext
    
    Dim NManager As JavaObject    = ctxt.RunMethod("getSystemService", Array("notification"))
    Dim ChannelId As String        = Application.LabelName&"_DEFAULT"
    Dim Channel As JavaObject    = NManager.RunMethod("getNotificationChannel",Array(ChannelId))
    If Not(Channel.IsInitialized) Then
        Log("Creation du channel " & ChannelId & "...")
        Channel.InitializeNewInstance("android.app.NotificationChannel", Array(ChannelId,Application.LabelName , 3))
        Channel.RunMethod("enableLights",Array(True))
        Channel.RunMethod("enableVibration",Array(True))
        Channel.RunMethod("setShowBadge",Array(True))
        NManager.RunMethod("createNotificationChannel",Array(Channel))
    End If
    
    NBuilder.InitializeNewInstance("android.app.Notification$Builder", Array(ctxt, ChannelId))
    NBuilder.RunMethodJO("setContentTitle", Array(xTitle)).RunMethodJO("setContentText", Array(xTexte))
    NBuilder.RunMethodJO("setAutoCancel", Array(Id>0)).RunMethodJO("setOngoing", Array(Id<0)) 
    NBuilder.RunMethodJO("setColorized", Array(True)).RunMethodJO("setColor", Array(Colors.White))
    NBuilder.RunMethodJO("setShowWhen", Array(True)).RunMethodJO("setWhen", Array(DateTime.Now))
    NBuilder.RunMethod("setSmallIcon", Array(Icon2Bitmap(Application.Icon)))
    If IsNumber(Number) Then NBuilder.RunMethod("setNumber", Array(Number)) 
    If Pkg<>""             Then NBuilder.RunMethod("setLargeIcon", Array(Tools.cd2b(pm.GetApplicationIcon(Pkg),40)))
    
    Dim in As Intent
    in.Initialize("","")
    in.Flags = Bit.Or(268435456, 131072)
    If GetType(xActivity)="java.lang.Class" Then
        in.SetComponent(Application.PackageName&"/"&xActivity.As(String).SubString(6))
    Else
        Dim comp As JavaObject = xActivity.As(JavaObject).RunMethod("getComponent",Null)
        If comp.IsInitialized Then in.SetComponent(comp.RunMethod("getPackageName",Null)&"/"&comp.RunMethod("getClassName",Null))
    End If
    Select True
        Case Regex.IsMatch("\w+=.*",xTag)
            Dim v() As String = Regex.Split("=|;",xTag)
            For i=0 To v.Length-1 Step 2
                in.PutExtra(v(i),v(i+1))
            Next
        Case xTag<>""
            in.PutExtra("Notification_tag",xTag)
    End Select
    Dim PendingIntent As JavaObject : PendingIntent.InitializeStatic("android.app.PendingIntent")
    Dim ContentIntent As Object     = PendingIntent.RunMethod("getActivity", Array(ctxt, Rnd(0, 0x7fffffff), in, Bit.Or(0, 33554432)))
    NBuilder.RunMethod("setContentIntent", Array(ContentIntent))

    Dim msg As JavaObject
    msg.InitializeNewInstance("android.app.Notification",Null)
    msg = NBuilder.RunMethod("build", Null)
    Id    = Abs(Id)
    NManager.RunMethod("notify",Array(Id,msg))
End Sub
Private Sub Icon2Bitmap(bmp As Bitmap) As Object
    Dim jo As JavaObject
    Return jo.InitializeStatic("android.graphics.drawable.Icon").RunMethod("createWithBitmap", Array(bmp))
End Sub
Alain
 
Upvote 0

Alain75

Member
With 2 more lines to deal with activities :
B4X:
    ...
    If GetType(xActivity)="java.lang.Class" Then
        in.SetComponent(Application.PackageName&"/"&xActivity.As(String).SubString(6))
    Else if xActivity Is Activity Then
        in = xActivity.As(Activity).GetStartingIntent
    Else
        Dim comp As JavaObject = xActivity.As(JavaObject).RunMethod("getComponent",Null)
        If comp.IsInitialized Then in.SetComponent(comp.RunMethod("getPackageName",Null)&"/"&comp.RunMethod("getClassName",Null))
    End If
    ...
Problem fixed :)
 
Upvote 0

AnandGupta

Expert
Licensed User
Longtime User
I am sorry that you don't understand my problem 😞. But using NB6 and passing an intent in Activity parameter of the build method crashs with the error previously reported. One of my friends developping with B4A has confirmed this bug.
Great that you solved your problem. 👍
Care to upload sample project with your changes/codes so that other members who may come across same problem, get the solution ?
 
Upvote 0

Alain75

Member
Okay but solution is quite simple : I use my own method to create notification in post #14 completed with 2 lines of post #16 until NB6 library will be fixed to manage intent in its Activity parameter (like Notification object).
 
Upvote 0

Alain75

Member
Okay ! I understand your position now : "it is by design". Below is the reason why I tried to pass an Intent in the Activity parameter :
  1. NB6 is more or less introduced as a better replacement of basic notification Object (because of Android evolution).
  2. NB6 exposes its Build parameters like Notification its SetInfo2 parameters, particularly for activity :
    image.jpg
  3. So, in my understanding, it was able to deal with its activity parameter in the same maner 🤔
It would be really great to extend (and not to fix) the NB6 library with this possibility. With this new functionality, the click on the notification will allow to launch another activity totally independantly of the initiating app 👏

Thanks !!!

Android part of my web site | My chrome extension
 
Upvote 0
Top