Android Question [Unsolved] ResumableSub, custom type return and obfuscation

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
I have a resumable sub, akin to:
B4X:
Public Sub DeviceGetStatus As ResumableSub
    Dim Result as MyCustomType
    ' .... more code
    Log("Device status request complete.")
     Return Result
End Sub
In another block, I call it with:
B4X:
Wait For (DeviceGetStatus) Complete(Status As MyCustomType)
This works fine in debug and release. When I do Release(obfuscated), this call errors out with:
B4X:
Device status request complete.
java.lang.Exception: Sub complete signature does not match expected signature.
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:215)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:197)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:193)
    at anywheresoftware.b4a.keywords.Common$14.run(Common.java:1773)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6523)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857)
java.lang.Exception: Sub complete signature does not match expected signature.
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:215)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:197)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:193)
    at anywheresoftware.b4a.keywords.Common$14.run(Common.java:1773)
    at android.os.Handler.handleCallback(Handler.java:790)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6523)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857)
I did not expierence this error prior to B4A 11.5. Was something changed, or was I doing it incorrectly all along?
 
Last edited:

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
No. Read my reply carefully, it tells you why it might be missed - and of course could be totally wrong!
I did read it, I just may have failed to follow what you were explaining ;)

For completeness, here's the get status routine for that test:
B4X:
Public Sub DeviceGetStatus
    Dim poJob As HttpJob
    Dim poResult As cgDeviceStatus
    
    poResult.Initialize
    poResult.CurrentScreen = DS_Unknown
    poResult.ResponseMessage = "Error communicating with device"

    Reset

    If msDeviceIP <> "" Then
        Dlog("Requesting device status...", Colors.Magenta)
        Dim psRequest As String =   $"http://${msDeviceIP}:8080/v2/pos?Action=Status&Format=XML"$
        ' issue request to device
        poJob.Initialize("", Me)
        Try
            ' send HTTP request
            poJob.GetRequest.Timeout = 15000
            poJob.Download(psRequest)
            ' wait for completion
            Wait For (poJob) JobDone(poJob As HttpJob)
            msRawDeviceResponse = poJob.GetString
            If poJob.Success Then
                Dim poTree As clsXmlTree = ParseXML(msRawDeviceResponse)
                If poTree.TreeIsEmpty  Then
                    msLastError = "Unknown response from device for status query: " & msRawDeviceResponse
                Else
                    poResult.Status = poTree.GetNodeTextFromRoot("Status")
                    Dim psVal As String = poTree.GetNodeTextFromRoot("CurrentScreen")
                    If IsNumber(psVal) Then
                        poResult.CurrentScreen = psVal
                    Else
                        poResult.CurrentScreen = DS_Unknown
                    End If
                    poResult.ResponseMessage = poTree.GetNodeTextFromRoot("ResponseMessage")
                    poResult.SerialNumber = poTree.GetNodeTextFromRoot("SerialNumber")
                    poResult.AppVer = poTree.GetNodeTextFromRoot("ApplicationVersion")
                    poResult.OSVer = poTree.GetNodeTextFromRoot("OSVersion")
                End If
            Else
                msLastError = poJob.ErrorMessage
            End If
        Catch
            msLastError = " Device Error: " & LastException.Message
        End Try
        poJob.Release
    End If
    If msLastError <> "" Then
        LogColor("clsCayanGenius.DeviceGetStatus: " & msLastError, Colors.Red)
    Else
        Dlog("Device status request complete.", Colors.Magenta)
    End If
    CallSubDelayed2(Me, "Status_Complete", poResult)
End Sub

And here's the relevant portion of the calling block:
B4X:
        Do While Not(mbAbort) And (DateTime.Now - plStart) < 120000 And Not(pbOnScreen)
            LogColor("Checking device status, before wait-for.", Colors.Magenta)
            DeviceGetStatus
            Wait for Status_Complete(CurrentStatus As cgDeviceStatus)
            Dlog("keyed status wait loop, device screen code is "& CurrentStatus.CurrentScreen, Colors.Magenta)
            If CurrentStatus.CurrentScreen = DS_MainPaymentCollection Then
                pbOnScreen = True
                Exit
            Else
                Dlog("Not swipe screen - " & CurrentStatus.CurrentScreen, Colors.Magenta)
                If CurrentStatus.CurrentScreen = DS_Unknown Then
                    Exit  'some error
                Else
                    Sleep(250)
                End If
            End If
        Loop
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
It's declared in the actual class itself, as I understand how custom types work it doesn't matter where they get declared.
And you are not willing to try declaring it in Main? In jRDC, the custom type has to be declared in Main or you'll encounter error messages. See https://www.b4x.com/android/forum/threads/error-with-jrdc2-with-b4a-client.111388/#post-694682. I know this is not exactly the same thing that you are encountering, but if type declaration location matters in one instance, it may matter in another.
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
And you are not willing to try declaring it in Main? In jRDC, the custom type has to be declared in Main or you'll encounter error messages. See https://www.b4x.com/android/forum/threads/error-with-jrdc2-with-b4a-client.111388/#post-694682. I know this is not exactly the same thing that you are encountering, but if type declaration location matters in one instance, it may matter in another.
For the sake of argument, I moved the type declaration to Main, recompiled and it produced the same results. I also tried moving it to the starter service and got the same result. It doesn't seem to make a difference where the custom type is declared.
 
Upvote 0

swChef

Active Member
Licensed User
Longtime User
I appreciate the thought, @swChef, but my goal here is to solve this with 11.5 and the most recent tools, not revert back to a previous version. I only mention it works under a previous version to help diagnose the problem (this is not a new piece of code that I'm trying to get to work).

The line that is failing is a Wait For statement, I'm not sure how I can screw that up, programmatically speaking. The resumable sub it is calling clearly completes and has ResumableSub as the return type.

The only "odd" bit to this entire function is that there is a previous HTTP job that is still running in the background started by the sub that hangs. The methodology is not my design, I have to work with what I'm given, I would have designed the device a bit differently and fired the programmer that suggested this design methodology.

I've already posted the complete code if you're curious, but the methodology is fairly straightforward:
  • Main Routine
    • Setup some variables
    • Call another resumable sub (no return type specified) that starts an HTTP job with 3 min. timeout and wait for http jobdone
    • Loop checking device status, this loop calls another resumable sub (with ResumableSub return type that has its own HTTP job with wait for jobdone) and waits for that sub to complete (this hangs)
    • Once status is met, exit loop
    • Loop checking for global var set by the earlier HTTP sub call (waiting for user input on device basically)
    • Return final result
Today I'll spend time modifying the Wait For to look for a specific event that I'll fire in the status sub. If that still fails, I'll try coding a loop that looks for a global var set by the status sub. I'll let you know what I find.
Jeff, I was just thinking something might be buggered with your new 11.5 environment. IIRC I've read on the forum folks have had an issue from time to time and reinstalled everything and then it was fine.
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
Jeff, I was just thinking something might be buggered with your new 11.5 environment. IIRC I've read on the forum folks have had an issue from time to time and reinstalled everything and then it was fine.
That was how I started, actually. I deleted both my Android SDK and JDK folders, and followed the B4A install instructions. So, I'm fairly confident the environment is alright.
 
Upvote 0

swChef

Active Member
Licensed User
Longtime User
That was how I started, actually. I deleted both my Android SDK and JDK folders, and followed the B4A install instructions. So, I'm fairly confident the environment is alright.
On such an install a year or couple ago, I had to redo the new installation and it corrected an odd issue. Can't recall the exact issue though. Might have posted on it.
 
Upvote 0

Jeffrey Cameron

Well-Known Member
Licensed User
Longtime User
After banging my head against this for a couple of weeks, I'm about ready to write this off and rewrite the class from scratch using nothing but wait loops.

Now the process is hanging in a wait for HTTP job done for some reason I cannot fathom. Here's the relevant code bit:
B4X:
                Dim poJob As HttpJob
                poJob.Initialize("", Me)
                poJob.GetRequest.Timeout = 5000
                LogColor("Starting keyed input request from: " & psRequest, Colors.Magenta)
                poJob.Download(psRequest)
                ' wait for completion
                Wait For (poJob) JobDone(poJob As HttpJob)
                msRawDeviceResponse = poJob.GetString
                LogColor("Keyed input request complete.", Colors.Magenta)
                If poJob.Success Then
I know the unit received the request, as it responds properly to the request, but the wait for never comes back. I see the first log statement, but I never see the "Keyed input request..." log statement and other events in the app keep marching on without issue. I've waited for up to 60 seconds for the HTTP request to timeout (even though it's set to 5 seconds) with nothing ever showing up in the log.

Does anyone have any final suggestions before I mark this as "[unsolved]" and move on?
 
Upvote 0
Top