Android Question Errors after going "async"

techgreyeye

Member
Licensed User
Longtime User
I've had a bit of time to go through one of my apps and finally remove all the DoEvents and Msgbox calls.

I ended up removing all the code modules and replacing them with classes, and converting lots of subs into resumables, wait for, sleep etc.

In a couple of my classes, I am getting this error when MsgboxAsync is called.

error log:
Error occurred on line: 165 (RebuildC)
java.lang.NullPointerException: Attempt to read from field 'java.lang.ref.WeakReference anywheresoftware.b4a.BA$SharedProcessBA.activityBA' on a null object reference in method 'java.lang.Object anywheresoftware.b4a.keywords.Common.Msgbox2Async(java.lang.CharSequence, java.lang.CharSequence, java.lang.String, java.lang.String, java.lang.String, anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper, anywheresoftware.b4a.BA, boolean)'
    at anywheresoftware.b4a.keywords.Common.Msgbox2Async(Common.java:486)
    at anywheresoftware.b4a.keywords.Common.MsgboxAsync(Common.java:464)
    at gtl.stockmate.rebuildc$ResumableSub_rebuildCount.resume(rebuildc.java:1130)
    at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resumeAsUserSub(DebugResumableSub.java:48)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:205)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:201)
    at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resume(DebugResumableSub.java:43)
    at anywheresoftware.b4a.keywords.Common$14.run(Common.java:1748)
    at android.os.Handler.handleCallback(Handler.java:942)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:226)
    at android.os.Looper.loop(Looper.java:313)
    at android.app.ActivityThread.main(ActivityThread.java:8810)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)

I ran debug and the crash re-occurred.
Then I put a break point on the MsgboxAsync call, and the app didn't crash.
I then moved the breakpoint to the start of the function, and again, the app didn't crash.

I had a similar problem but different error message with MsgboxAsync2 in a different sub as well.

What could be going on here?

I have replaced a lot of code, and I have only had issues in these two places.
What could be going on?
 

techgreyeye

Member
Licensed User
Longtime User
Where is the code snipped or example project what shows the error?
I'd hoped that the error description would be enough, but I've been making an example which sheds more light on the problem. I've attached a very simple project.

This is tested on a few different devices with different Android versions and is consistent behaviour.

The function "crash" is in a resumable sub in a standard class.

The crash occurs on the second MsgboxAsync call. It happens whether you Wait For or not.
It doesn't crash when running debug if there is a breakpoint in the function, regardless of whether you have hit the breakpoint or not.
It doesn't crash if you remove the call to sleep.



crashing function:
Public Sub crash As ResumableSub
    MsgboxAsync("I don't crash here","1")
    Wait For MsgBox_Result (res As Int)
    Log("1")
    Sleep(0)
    Log("2")
    MsgboxAsync("I crash here", "2")
    Wait For MsgBox_Result (res As Int)
    Log("3")
    Return False
End Sub

call the crashing function:
Sub Button1_Click
    Dim tc As test
    tc.Initialize
    tc.crash
End Sub

log:
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create (first time) **
** Activity (main) Resume **
1
2
java.lang.RuntimeException: java.lang.NullPointerException: Attempt to read from field 'java.lang.ref.WeakReference anywheresoftware.b4a.BA$SharedProcessBA.activityBA' on a null object reference in method 'java.lang.Object anywheresoftware.b4a.keywords.Common.Msgbox2Async(java.lang.CharSequence, java.lang.CharSequence, java.lang.String, java.lang.String, java.lang.String, anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper, anywheresoftware.b4a.BA, boolean)'
    at anywheresoftware.b4a.keywords.Common$14.run(Common.java:1750)
    at android.os.Handler.handleCallback(Handler.java:942)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:226)
    at android.os.Looper.loop(Looper.java:313)
    at android.app.ActivityThread.main(ActivityThread.java:8810)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Caused by: java.lang.NullPointerException: Attempt to read from field 'java.lang.ref.WeakReference anywheresoftware.b4a.BA$SharedProcessBA.activityBA' on a null object reference in method 'java.lang.Object anywheresoftware.b4a.keywords.Common.Msgbox2Async(java.lang.CharSequence, java.lang.CharSequence, java.lang.String, java.lang.String, java.lang.String, anywheresoftware.b4a.objects.drawable.CanvasWrapper$BitmapWrapper, anywheresoftware.b4a.BA, boolean)'
    at anywheresoftware.b4a.keywords.Common.Msgbox2Async(Common.java:486)
    at anywheresoftware.b4a.keywords.Common.MsgboxAsync(Common.java:464)
    at b4a.example.test$ResumableSub_crash.resume(test.java:81)
    at anywheresoftware.b4a.keywords.Common$14.run(Common.java:1748)
    ... 8 more
 

Attachments

  • AsyncCrash.zip
    9.4 KB · Views: 98
Upvote 0

Alexander Stolte

Expert
Licensed User
Longtime User
I'd hoped that the error description would be enough
It is always important to see what code the person is using.

But unfortunately I can't really help you any further, I couldn't confirm my suspicions.
But maybe someone else knows why the dialog is not compatible with a Sleep.
 
Upvote 0

techgreyeye

Member
Licensed User
Longtime User
It is always important to see what code the person is using.

But unfortunately I can't really help you any further, I couldn't confirm my suspicions.
But maybe someone else knows why the dialog is not compatible with a Sleep.

Thanks anyway.

I've extended my investigation to look into my other crash, and it's similar, but catching exceptions.

crashing function 2:
public Sub crash2 As ResumableSub
    Dim i As Int
    Try
        i = "doesn't crash"
    Catch
        Log(i & " " & LastException)
    End Try
    Sleep(0)
    Try
        i = "does crash"
    Catch
        Log(i & " " & LastException)
    End Try
    Return False
End Sub

call crashing function 2:
Sub Button1_LongClick
    Dim tc As test
    tc.Initialize
    tc.crash2
End Sub

Log:
** Service (starter) Start **
** Activity (main) Create (first time) **
** Activity (main) Resume **
0 (NumberFormatException) java.lang.NumberFormatException: For input string: "doesn't crash"
java.lang.RuntimeException: java.lang.NullPointerException: Attempt to write to field 'java.lang.Exception anywheresoftware.b4a.BA$SharedProcessBA.lastException' on a null object reference in method 'void anywheresoftware.b4a.BA.setLastException(java.lang.Exception)'
    at anywheresoftware.b4a.keywords.Common$14.run(Common.java:1750)
    at android.os.Handler.handleCallback(Handler.java:942)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:226)
    at android.os.Looper.loop(Looper.java:313)
    at android.app.ActivityThread.main(ActivityThread.java:8810)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Caused by: java.lang.NullPointerException: Attempt to write to field 'java.lang.Exception anywheresoftware.b4a.BA$SharedProcessBA.lastException' on a null object reference in method 'void anywheresoftware.b4a.BA.setLastException(java.lang.Exception)'
    at anywheresoftware.b4a.BA.setLastException(BA.java:663)
    at b4a.example.test$ResumableSub_crash2.resume(test.java:216)
    at anywheresoftware.b4a.keywords.Common$14.run(Common.java:1748)
    ... 8 more
 

Attachments

  • AsyncCrash.zip
    9.5 KB · Views: 96
Upvote 0

Spavlyuk

Active Member
Licensed User
Looks like an edge case for activity projects where calling Sleep before MsgboxAsync causes a crash, while in a B4XPages it does not.
You can try the following workaround which does not crash for me.

B4X:
Public Sub crash As ResumableSub
    MsgboxAsync("I don't crash here","1")
    Wait For MsgBox_Result (res As Int)
    Log("1")
    Wait For (DoTheThing) Complete (Success As Boolean)
    Log("2")
    MsgboxAsync("I crash here", "2")
    Wait For MsgBox_Result (res As Int)
    Log("3")
    Return False
End Sub

Private Sub DoTheThing As ResumableSub
    Sleep(0)
    Return True
End Sub
 
Upvote 0

techgreyeye

Member
Licensed User
Longtime User
Looks like an edge case for activity projects where calling Sleep before MsgboxAsync causes a crash, while in a B4XPages it does not.

Thanks Spavlyuk. That does work for both the MsgboxAsync and the exception handling, so I have a workaround.

I wonder if anyone has an explanation for what is actually happening though.
 
Upvote 0

Spavlyuk

Active Member
Licensed User
Probably has to do with the internals of B4A.
Calling Sleep before MsgboxAsync seems somewhat weird though.
I've never needed to do that nor have I seen a similar thread. Is there a use case behind it?
 
Upvote 0

techgreyeye

Member
Licensed User
Longtime User
Probably has to do with the internals of B4A.
Calling Sleep before MsgboxAsync seems somewhat weird though.
I've never needed to do that nor have I seen a similar thread. Is there a use case behind it?

In the real code, I was reading a large data file and cross referencing with a large array, an operation that can take 10 seconds. ProgressDialogShow wasn't showing/updating so the sleeps were in the code for that, not for the MsgboxAsync. The code I put up here is just minimum required to reproduce the crash.
 
Upvote 0

Spavlyuk

Active Member
Licensed User
If you're doing heavy calculations on the UI thread, you should consider offloading such tasks to a background thread.
I don't have much experience in this area but I would suggest trying out a threading library or using a service.
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
or using a service
Please note, a service does not run on a separate thread

Caution: A service runs in the same process as the application in which it is declared and in the main thread of that application by default. If your service performs intensive or blocking operations while the user interacts with an activity from the same application, the service slows down activity performance. To avoid impacting application performance, start a new thread inside the service.
Source: https://developer.android.com/develop/background-work/services#:~:text=Caution: A service runs in the same process as the,service slows down activity performance.
 
Last edited:
Upvote 0

OliverA

Expert
Licensed User
Longtime User
I've extended my investigation to look into my other crash, and it's similar, but catching exceptions.
@techgreyeye: you may have found a bug—the same exception-catching test works properly under B4J, yet bombs out under B4A. I don't know what the behavior is in B4i regarding this, but B4J acting differently indicates that this issue is a bug in B4A.

Attaching B4J project that shows that the try/catch issue does not occur in B4J as it does in B4A

Update: @techgreyeye: you may want to open a bug report on this issue
 

Attachments

  • 20240301_ResumableCrash.zip
    2.6 KB · Views: 128
Upvote 0
Top