Android Question [solved] [B4xPages] Delegating signature error

udg

Expert
Licensed User
Longtime User
Ok, it must be really simple but I can't see it (even after my third espresso in the day..).
Compiling Release (obfuscated)
Error: java.lang.Exception: Sub abc_suresult signature does not match expected signature.

In Main I have
B4X:
Sub Get_SUResult(aList As List)     'Answer from Activity PaymentResult
    Log(aList.Get(0))                        'prints ok
    B4XPages.GetManager.RaiseEvent(B4XPages.GetManager.GetTopPage, "ABC_SUResult", Array(aList))
End Sub
It's called from a second activity (PaymentResult) by
CallSubDelayed2(Main, "Get_SUResult", l1)
where l1 is a list which has a single item, a string coming back from the external payment system

In b4xMainPage (being the top and only page), I have
B4X:
Sub ABC_SUResult(alist As List)
    Log("here I am")
    Dim s As String = alist.get(0)
    Log(s)
End Sub
but it never arrives here due to the above error.
 

udg

Expert
Licensed User
Longtime User
Sure, here it is:

*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Get (Intent) Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=eu.dgc.sumuptest/.main }
** Activity (main) Pause event (activity is not paused). **
** Activity (paymentresult) Create, isFirst = true **
** Activity (paymentresult) Resume **
(Intent) Intent { act=eu.dgc.sumuptest.paymentresult cmp=eu.dgc.sumuptest/.paymentresult (has extras) }
Transaction failed.
SumUp-Answer: Transaction failed.
mainpage
** Activity (paymentresult) Pause, UserClosed = true **
java.lang.Exception: Sub abc_suresult signature does not match expected signature.
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:215)
at anywheresoftware.b4a.keywords.Common$11.run(Common.java:1178)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7642)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:503)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

What I am doing is a porting to B4xPages of an existing demo project using SumUp API.
No problem to export the whole project (that is intended to go to the original thread anyway)
 
Last edited:
Upvote 0

udg

Expert
Licensed User
Longtime User
Here is the whole project.

Edit: attachment removed. See post #12 below for a working workaround.
 
Last edited:
Upvote 0

udg

Expert
Licensed User
Longtime User
And here's the Stack Trace. BTW, I wasn't aware of that Log_StackTrace sub.. :-(

*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Get (Intent) Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=eu.dgc.sumuptest/.main }
** Activity (main) Pause event (activity is not paused). **
** Activity (paymentresult) Create, isFirst = true **
** Activity (paymentresult) Resume **
(Intent) Intent { act=eu.dgc.sumuptest.paymentresult cmp=eu.dgc.sumuptest/.paymentresult (has extras) }
Transaction failed.
****************
eu.dgc.sumuptest.paymentresult: _vvvvvvvvvvvvv5
eu.dgc.sumuptest.paymentresult: _activity_resume
java.lang.reflect.Method: invoke
anywheresoftware.b4a.BA: raiseEvent2
anywheresoftware.b4a.BA: raiseEvent
eu.dgc.sumuptest.paymentresult: afterFirstLayout
eu.dgc.sumuptest.paymentresult: access$000
eu.dgc.sumuptest.paymentresult$WaitForLayout: run
android.os.Handler: handleCallback
android.os.Handler: dispatchMessage
android.os.Looper: loop
android.app.ActivityThread: main
java.lang.reflect.Method: invoke
com.android.internal.os.RuntimeInit$MethodAndArgsCaller: run
com.android.internal.os.ZygoteInit: main
SumUp-Answer: Transaction failed.
mainpage
** Activity (paymentresult) Pause, UserClosed = true **
java.lang.Exception: Sub abc_suresult signature does not match expected signature.
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:215)
at anywheresoftware.b4a.keywords.Common$11.run(Common.java:1178)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7642)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:503)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
--------- beginning of crash
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Here is the whole project
1629791249631.png
 
Upvote 0

udg

Expert
Licensed User
Longtime User
It's the one mentioned in post #3 above.
I'm trying to convert Roland's original demo code to the B4xPages model. Everything seems to work until I reach the last step: delegating from Main to MainPage in order to report the answer from the payment system.

I feel it's something stupid, but I can't see it...
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
It is somewhat convoluted and I don't have much patience today.

When I start the app I only see the B4XMainPage, from which I cannot exit (go to the other Activity).

If you want to convert to a B4XPages project, why do you have that second Activity? Normally you should only have the Main.

However the problem is in that CallSubDelayed with the app compiled in obfuscated mode; if I remember correctly you cannot call a routine of an Activity that is not in the foreground that way (even if the problem seems to be the obfuscated routine name).
 
Upvote 0

udg

Expert
Licensed User
Longtime User
I found a temporary workaround!

In Main (Sub Get_SUResult) I set a global variable in MainPage (to pass the response from the payment system) then call a no-params sub like this:
B4XPages.GetManager.RaiseEvent(B4XPages.GetManager.GetTopPage, "test_1", Null)

The mistery about the non-matching signature is still there, but at least now I can go on with the development.
Three days left to be ready....

@LucaMs : it's a requirement to have two activities (one to send out transaction data and one to receive the feedback), but there's no problem with that in B4xPages. BTW, CallSubDelayed "wakes up" the destination activity (if the app is not in the background), so no problem there too.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
it's a requirement to have two activities (one to send out transaction data and one to receive the feedback),
Can't you do it with two B4XPages? The one not on top - not visible - is always active.

BTW, CallSubDelayed "wakes up" the destination activity (if the app is not in the background), so no problem there too.
Yes, I remembered CallSubDelayed bringing the target Activity to foreground but I didn't remember in what condition it couldn't :confused:
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi all,

please find attached a copy of the project that seems to work.
The flow is: MainPage-SumUp-PaymentResult-Main-MainPage
In this demo I use the same page (B4xMainPage) to send out transaction data and to receive the answer from SumUp. It could be done on two distinct pages.
Another difference from original code is that activity PaymentResult doesn't show any layout. It's used just to hand over the transaction result to Main.

@Erel : please can you verify that, at least logically, it works as it should? My goal is to add it to the original thread so to show a way to use B4xPages with Roland's lib.
BTW, I left in commented code (in Main_Get_SUResult) that is the one raising the signature error this thread is about. I still can't see what's wrong with it.
 

Attachments

  • SumUpTest.zip
    14.3 KB · Views: 220
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
1. I don't understand why you need to delegate it to the Main module. Why not raise the event from the payment activity?

2.
The issue can be solved with:
B4X:
B4XPages.GetManager.RaiseEvent(B4XPages.GetManager.GetTopPage, "abc_suresult", Array(aList,1))

B4X:
Sub abc_suresult(alist As Object, code As Int)
 Dim list As List = alist

It is related to the conversion of List (a wrapper object) when you put it inside the array of objects.
 
  • Like
Reactions: udg
Upvote 0

udg

Expert
Licensed User
Longtime User
Hi Erel, thanks for clarifying the subject.

1. I don't understand why you need to delegate it to the Main module. Why not raise the event from the payment activity?
I see the Main activity as the "entrance point" to the B4xPages, so the idea was "call Main from payment activity and let Main raise the event for the top page".
Do you suggest to use that same B4XPages.GetManager.RaiseEvent statement in payment activity instead of the CallSubDelayed one?
Inspired by your reply I moved the cursor on the B4xpages item and saw it is a static module, so, yes, it is available all the time to all the modules in the app. Good to know.

It is related to the conversion of List (a wrapper object) when you put it inside the array of objects.
Good point. Now it's clear why my attempts failed one after the other :)
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Only in that case (that RaiseEvent event)?
I answer to myself :)

That "RaiseEvent" receives only one parameter to pass to the called event, yet this event, in this case, requires 2.

Evidently RaiseEvent is done in such a way that it transforms the contents of that Array into objects, and then uses a CallSubDelayed which can have 0 to 2 parameters, as usual (obviously it will choose CallSubDelayed, CallSubDelayed2 or CallSubDelayed3).


[I have developed a probably identical or nearly identical routine that I use in my classes :)]

B4X:
Private Sub RaiseEvent(EvName As String, Params As List, Delayed As Boolean)
    Dim FullRoutineName As String
    FullRoutineName = mEventName & "_" & EvName
    If SubExists(mCallback, FullRoutineName) Then
        If Not(Params.IsInitialized) Then
            If Delayed Then
                CallSubDelayed(mCallback, FullRoutineName)
            Else
                CallSub(mCallback, FullRoutineName)
            End If
        Else
            If Delayed Then
                Select Params.Size
                    Case 0
                        CallSubDelayed(mCallback, FullRoutineName)
                    Case 1
                        CallSubDelayed2(mCallback, FullRoutineName, Params.Get(0))
                    Case 2
                        CallSubDelayed3(mCallback, FullRoutineName, Params.Get(0), Params.Get(1))
                    Case Else ' > 2
                        CallSubDelayed2(mCallback, FullRoutineName, Params)
                End Select
            Else
                Select Params.Size
                    Case 0
                        CallSub(mCallback, FullRoutineName)
                    Case 1
                        CallSub2(mCallback, FullRoutineName, Params.Get(0))
                    Case 2
                        CallSub3(mCallback, FullRoutineName, Params.Get(0), Params.Get(1))
                    Case Else ' > 2
                        CallSub2(mCallback, FullRoutineName, Params)
                End Select
            End If
        End If
    End If
End Sub
and looking at it now, I realize that it would be better if I passed the callback to it, rather than using the one passed to the class (that Private ;) mCallback) ; this way I could use the routine in a code module :confused:
 
Last edited:
Upvote 0
Top