I'm updating an old app hopefully to stabalize it a bit (seems to go in endless loop sometimes on newer phones).
It's build on async streams and while I used a several try/catch blocks to intercept errors I'm trying to do it in a more clean way.
Now I noticed that the async stream _error function sometimes recieves a null object which makes my connection closing routine freak out on the .isInitilized check.
error:
05/03/2024 11:18:46 : 192.168.11.5 java.lang.NullPointerException: Attempt to invoke virtual method 'boolean anywheresoftware.b4a.randomaccessfile.AsyncStreams.IsInitialized()' on a null object reference ( java.lang.NullPointerException: Attempt to invoke virtual method 'boolean anywheresoftware.b4a.randomaccessfile.AsyncStreams.IsInitialized()' on a null object reference
What's the right way to detect this null object so that I can skip the closing sub?
And why does it pass this null object and not the actual streaming one?
I am just guessing here, but perhaps AsynchStreams crashed out but didn't successfully close the feeder stream, and that feeder stream still (somehow) knew the name of the error event to call. ?
the problem is that I didn't get this error om my test phones yet or I don't know when this happend or how I can force that situation/error.
I tried manual disconnects, disabling wifi etc but in my case the stream just reconnects without problems.
The problem is that when I apply the change my colleague needs to manually update the app on a dozen phones so I prefer waiting for the right way than just guessing.
I am pretty sure that, if no better solution arises, then an If PotentiallyNullObject = Null test before the PotentiallyNullObject.IsInitialized would work as a last resort safety net to catch app before it goes down in flames.
First spotted in B4A 12.50, still happening in 12.80. I've tested this on a few devices with different Android versions and it crashes on all three. If I call MsgboxAsync or Msgbox2Async after a sleep within a ResumableSub in a class module, the app crashes. If I have a try...catch block after...
If the first condition is true (in this case senderAsyncStream is Null), then it will short circuit and will not test the 2nd condition. The only time the 2nd condition will be tested if the first condition fails, meaning that senderAsyncStream is NOT null and therefore one can safely use the Object's methods.
the null or initialized check to exit the sub it not needed as it keeps the error loop alive.
my close connection has 2 main loops.
first it scans the connection list to figure out what ip the request is coming from.
in the second loop it checks all connections and closes all those from the found IP just in case there are multiple.
in the second loop I just change the check for the found ip to (found ip or "") the ip value is "" when no ip was found in the first loop (in case of null object)
so it either closes the given IP connections or all connections when a null object passes.
not clean but not a real issue either as the listeners will reconnect after max 15 seconds.
why the _error keeps getting called when the socket is not closed I don't know.
From what I can tell, if the event is queued via the line
B4X:
addMessageToPausedMessageQueue(event, this);
then the sender information is lost. If that is true, it may be that you have to encapsulate each AsyncStream object within another Class module that tracks that AsyncStream's objects error events and then closes the AsyncStream object associated with the class, instead of relying on the Sender object of the event. I hope this logic makes sense...