Android Question Real-time log messages

RB Smissaert

Well-Known Member
Licensed User
Trying to add real-time log messages to my app, so I can investigate problems if not a the PC.
The running code should pause while the message is showing and this is not as easy as I thought it
would be.

Currently I am trying this:

In a code module (called General) I have this:

B4X:
Public Sub RunLog(strLogText As String)
 CallSub2("Main", "RunLog2", strLogText)
End Sub
This is called mainly from Main, eg:

B4X:
General.RunLog("ChangeMenuGroup, iCurrentMenuGroup: " & iCurrentMenuGroup)
In Main I have:

B4X:
Sub RunLog2(strLogText As String)
 If General.bLog Then
  Log(strLogText)
 End If
 If General.bLog2SQL Then
  StoreLogMsg(strLogText)
 End If
 If General.bLog2Msg Then
  'otherwise the previous dialog will be replaced by a new one
  'need to press OK first
  '------------------------------------------------------------
  Do While Dialog.IsVisible
   Sleep(1)
  Loop
  Dim rs As ResumableSub = Dialog.Show(Activity, Array As Object("OK", "Stop Msg"), _
         "Log text", "", strLogText, _
         -1, False, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Null, False, arrS, 0)
  Wait For (rs) Complete (strResult As String)
  If strResult = "Stop Msg" Then
   General.bLog2Msg = False
   chkLog2Msg.Checked = False
  End If
 End If
End Sub
Dialog.Show is an adapted B4X dialog in a class and this is a ResumableSub. The code is a bit long
as it has many options, but it works fine and I use this in many places and the code flow will wait
for the dialog to be finished. I can post this if needed.
In this case though the code flow is not paused by the dialog and also I can't stop the dialog messages
by doing General.bLog2Msg = False. I have a feeling the problem is with the Sleep(1) in Sub RunLog2, but I can't do without that.

I tried the real-time Log messages with ToastMessageShow, but that doesn't pause the code flow either.

Any suggestions how to solve this problem?

RBS
 

RB Smissaert

Well-Known Member
Licensed User
I had a look at that and changed the Msg Sub, so it returns a ResumableSub:

B4X:
Sub RunLog2(strLogText As String)
 
 If General.bLog Then
  Log(strLogText)
 End If
 
 If General.bLog2SQL Then
  StoreLogMsg(strLogText)
 End If
 
 If General.bLog2Msg Then
  Dim rs As ResumableSub = RunLog3(strLogText)
  Wait For (rs) Complete (bDone As Boolean)
 End If

End Sub

Sub RunLog3(strLogText As String) As ResumableSub
 
 Dim rs As ResumableSub = Dialog.Show(Activity, Array As Object("OK", "Stop Msg"), _
       "Log text", "", strLogText, _
       -1, False, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Null, False, arrS, 2)
 Wait For (rs) Complete (strResult As String)
 
 If strResult = "Stop Msg" Then
  General.bLog2Msg = False
  chkLog2Msg.Checked = False
 End If
 
 Return(True)
 
End Sub
Still the code flow doesn't wait for the Dialog to be dismissed.

RBS
 

RB Smissaert

Well-Known Member
Licensed User
If it is purely to pause to read a message while debugging then just use good old modal MsgBox. It still works fine, though I would only use it for debugging and not in a release version of an app.
Thanks, will bear that in mind if I can't figure this out.
Dialog is nicer as I have option to do various actions with various buttons.

RBS
 

agraham

Expert
Licensed User

RB Smissaert

Well-Known Member
Licensed User
Msgbox supports returning one of three button presses, if you want more, or to run events while paused, you can use a CustomDialog dialog shown modally from my Dialogs2 library.

https://www.b4x.com/android/forum/t...-the-original-dialogs-library.106938/#content

In more recent B4A versions not all events from Views will run from a CustomDialog shown modally but Button_Click does.
Thanks, will have a look at your Dialogs2.
Just puzzles me why in this case my Dialog.Show doesn't behave modal.

RBS
 

OliverA

Expert
Licensed User
When the code hits the wait for in RunLog3, it stops and continues processing code of the calling method. In this case RunLog2. Since there is a wait there, RunLog2 stops processing and continues the code that ran it. The method RunLog has a return after calling CallSub and thus returns. So the next code execution are the lines of code after whatever called General.RunLog. So no, your Dialog is not modal. That’s actually the whole point of wait for. It’s the anti modal (blocking) way of doing things. If you want to block, then use non-async/non-wait for methods
 

RB Smissaert

Well-Known Member
Licensed User
RunLog2 should also return ResumableSub and you should call it with Wait For.
I can see that if I call RunLog2 from Main with Wait For it all runs perfectly fine as I expected.
Just need to figure out now how I can call RunLog2 with Wait For from a code module.

RBS
 

RB Smissaert

Well-Known Member
Licensed User
I can see that if I call RunLog2 from Main with Wait For it all runs perfectly fine as I expected.
Just need to figure out now how I can call RunLog2 with Wait For from a code module.

RBS
Had another look at this and it looks this doesn't work well with ResumableSub, for 2 reasons:
1. Where before there was one line to do the log, eg: clsLog.RunLog("just testing") there now need to be 2 lines, eg:

B4X:
 Dim rs As ResumableSub = clsLog.RunLog("just testing")
 Wait For (rs) Complete (bDone As Boolean)
Not a major problem, but still a hassle.

2. More importantly, I can't do the above code in Subs that return return simple types. Return needs to be nil or ResumableSub.

I think the best way might be Agraham's Dialog2.

RBS
 

Erel

Administrator
Staff member
Licensed User
Not a major problem, but still a hassle.
???

B4X:
Wait For (clsLog.RunLog("just testing")) Complete (bDone As Boolean)
More importantly, I can't do the above code in Subs that return return simple types. Return needs to be nil or ResumableSub.
That's true. It should be resumable subs all the way up. You cannot hold the main thread. Any solution that tries to hold the main thread should only be used during debugging as it will cause all kinds of problems.
 

RB Smissaert

Well-Known Member
Licensed User
???

B4X:
Wait For (clsLog.RunLog("just testing")) Complete (bDone As Boolean)

That's true. It should be resumable subs all the way up. You cannot hold the main thread. Any solution that tries to hold the main thread should only be used during debugging as it will cause all kinds of problems.
???
Yes, sorry, forgot you could put both statements on one line

> Any solution that tries to hold the main thread should only be used during debugging
So, how about Agraham's Dialog2 modal dialog? Would that cause problems as well?

Maybe the best option is to store the log messages and look at time, non real-time.

RBS
 

Erel

Administrator
Staff member
Licensed User
So, how about Agraham's Dialog2 modal dialog? Would that cause problems as well?
Yes. They are based on the same implementation as Msgbox and DoEvents. It is just no longer possible to hold the main thread. It was possible in the early days of Android.

Resumable subs work completely differently.
 

RB Smissaert

Well-Known Member
Licensed User
Yes. They are based on the same implementation as Msgbox and DoEvents. It is just no longer possible to hold the main thread. It was possible in the early days of Android.

Resumable subs work completely differently.
OK, thanks.

Related to this:
> 2. More importantly, I can't do the above code in Subs that return return simple types. Return needs to be nil or ResumableSub.

I suppose what I could do is make those Subs return nil and get the result of the Sub via a module level variable.
Will get messy though, but can't see any other solution other than just forget about real time log messages.

RBS
 

OliverA

Expert
Licensed User
2. More importantly, I can't do the above code in Subs that return return simple types. Return needs to be nil or ResumableSub.
What am I not getting about this statement? Even if you declare a sub as ResumableSub, it still can return a value (a single one, be it a "simple" type or a map/list/Object). That's what the whole Complete portion of the Wait For statement is all about.
 
Top