B4J Question Embedded java question

wl

Well-Known Member
Licensed User
Longtime User
I'm currently writing B4J with embedded java code.

When I call a method in a B4 class from within java in debug mode I need to provide the reference to the B4J object.

When I do the same in release mode the param can not be provided.

Where is this difference coming from and how to write clear code that can be used in both debug and release mode ?

The code below is part of a B4 Class...

In debug mode:
B4X:
public Sub Demo
    Dim obj As JavaObject = Me
    obj.RunMethod("StartJava", Null)
End Sub

public Sub CallBack ()
    Log ("in CallBack")
End Sub


#if java

public void StartJava {
    _callback(this);   //NOTICE THE PRESENCE OF THE PARAM !
}
#End If

In release mode:

B4X:
public Sub Demo
    Dim obj As JavaObject = Me
    obj.RunMethod("StartJava", Null)
End Sub

public Sub CallBack ()
    Log ("in CallBack")
End Sub


#if java

public void StartJava {
    _callback();   //NOTICE THE ABSENCE OF THE PARAM !
}
#End If
 

OliverA

Expert
Licensed User
Longtime User
Upvote 0

wl

Well-Known Member
Licensed User
Longtime User
use #if DEBUG? (https://www.b4x.com/android/forum/threads/conditional-compilation-build-configurations.40746/)

B4X:
#if DEBUG
#if java

public void StartJava {
    _callback(this);   //NOTICE THE PRESENCE OF THE PARAM !
}
#End If
#Else
#if java

public void StartJava {
    _callback();   //NOTICE THE ABSENCE OF THE PARAM !
}
#End If
#End If


Yes: this is possible but this is just a small demo. In reality the java code is much longer.... and I don't want to duplicate the entire code block
Bad for maintenance ...

the #ifdef debug can not be WITHIN #ifdef java so I can't just put the different code lines in #ifdef DEBUG / #ifdef RELEASE
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
What java are you using?
The reason I ask is that
B4X:
public void StartJava {
    _callback();
}
will not compile unless I add () after StartJava
B4X:
public void StartJava() {
    _callback();
}
 
Upvote 0

wl

Well-Known Member
Licensed User
Longtime User
What java are you using?
The reason I ask is that
B4X:
public void StartJava {
    _callback();
}
will not compile unless I add () after StartJava
B4X:
public void StartJava() {
    _callback();
}

My mistake: I also have the brackets ... Probably copied the code even before I tested it (tested it meanwhile though :))...
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
I'm pretty sure you can do this. Not elegant, but it let's you isolate the differences. It's a little ugly looking, especially with such a short code example.
B4X:
#if java
public void StartJava {
#End If ' Java
#If DEBUG
#if Java
    _callback(this);   //NOTICE THE PRESENCE OF THE PARAM !
#End If ' Java
#Else ' Not DEBUG mode
#if Java
    _callback();   //NOTICE THE ABSENCE OF THE PARAM !
#End If ' Java
#End If ' DEBUG 
#if Java
}
#End If
 
Upvote 0

wl

Well-Known Member
Licensed User
Longtime User
I'm pretty sure you can do this. Not elegant, but it let's you isolate the differences. It's a little ugly looking, especially with such a short code example.
B4X:
#if java
public void StartJava {
#End If ' Java
#If DEBUG
#if Java
    _callback(this);   //NOTICE THE PRESENCE OF THE PARAM !
#End If ' Java
#Else ' Not DEBUG mode
#if Java
    _callback();   //NOTICE THE ABSENCE OF THE PARAM !
#End If ' Java
#End If ' DEBUG
#if Java
}
#End If


That could be an option I did not think of ... :) Indeed a bit messy ... I guess the "man itself" (Erel) would be the only one capable of providing a nicer solution ....

UPDATE: it seems you CAN do this kind of construction ...
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
How about
B4X:
 Dim inline As JavaObject
 inline = Me
#if DEBUG 
 inline.RunMethod("StartJava",Null)
#ELSE
 inline.RunMethod("StartJava",Array(1))
#END IF
End Sub
Sub CallBack()
 Log("in call back no param")
End Sub
Sub CallBack1(o As Object)
 Log("in call back with param "&o)
End Sub
'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
 Return True
End Sub
#if java
public static void StartJava() throws Exception{
 _callback();
}
public static void StartJava(Object o) throws Exception {
 _callback1(o);
}
#End If
 
  • Like
Reactions: wl
Upvote 0

wl

Well-Known Member
Licensed User
Longtime User
How about
B4X:
 Dim inline As JavaObject
 inline = Me
#if DEBUG
 inline.RunMethod("StartJava",Null)
#ELSE
 inline.RunMethod("StartJava",Array(1))
#END IF
End Sub
Sub CallBack()
 Log("in call back no param")
End Sub
Sub CallBack1(o As Object)
 Log("in call back with param "&o)
End Sub
'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
 Return True
End Sub
#if java
public static void StartJava() throws Exception{
 _callback();
}
public static void StartJava(Object o) throws Exception {
 _callback1(o);
}
#End If


Nice idea. Took this one small step further: just put the B4J callback method signature in #ifdef

B4X:
#if debug
public Sub CallBack ()
#Else
public Sub CallBack (obj As Object)
#end if

Log ("in CallBack")
End Sub



#if java
public void StartJava() throws Exception {
        _callback(this);
}
#End If
 
Last edited:
Upvote 0

wl

Well-Known Member
Licensed User
Longtime User
I guess this difference in DEBUG and RELEASE mode has to do with the internal workings of B4J that transforms the BASIC code to Java before compiling ...
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
So "this" is not internalized in debug mode? At least you made it sound like it here
When I call a method in a B4 class from within java in debug mode I need to provide the reference to the B4J object.
and by providing only one callback sub in your first example without parameter. So what is it? I'm just being curious here because post #8 and #9 suddenly expose this to the callback sub (by having two different sub signatures).
 
Upvote 0

wl

Well-Known Member
Licensed User
Longtime User
Not entirely sure what you mean.

In debug mode the the javacode will look for a B4j method with as first (only) parameter a reference to the object (B4J) it is part of (thus the "this").
In release mode the B4J method should not have this parameter.

But as far as internal working is concerned this is not relevant since even in release mode I can have a reference to the object it is part of (by calling the Basic statement "me").

It's just that the compiler complains in debug mode without the parameter in the callback signature ...
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
I can't see how you are calling the B4J sub 'CallBack()' and passing a parameter, as the compiler complains when I tried, as the method is not matched.
 
Upvote 0

wl

Well-Known Member
Licensed User
Longtime User
DO NOTE: my code is part of a B4J class ... This *IS* important ....

When the Java is embedded in a module (not a B4J class) there seems no difference in building a DEBUG and a RELEASE build. In both cases the callback does NOT have a parameter...
Problems arise when the code is part of a B4J class ... This seems to make sense in a way because when the code is part of a module there is fact no "this" ...

Below the entire code of my B4J class ("demo"). Thanks to the #ifdef around the B4J callback method signature I can build both in DEBUG as well as in RELEASE mode (NOT release with obfuscation because this won't work ...):

B4X:
'Class module
Sub Class_Globals
 
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
 
End Sub

public Sub DoDemo
    Dim obj As JavaObject = Me
    obj.RunMethod("StartJava", Null)
End Sub

#if debug
public Sub CallBack ()
#Else
public Sub CallBack (obj As Object)
#end if

Log ("in CallBack")
End Sub



#if java
public void StartJava() {
    try {
        _callback(this);
    }catch (Exception ex) {
 
    }
}
#End If
[/QUOTE]
 
Last edited:
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Sorry, I assumed the original code was in the main module. My bad :)
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
See https://www.b4x.com/android/forum/t...vent-from-inline-java-code.50161/#post-313304.
This works in debug, release, with rapid debug, etc. Renamed callback sub as per link's suggestion (see point #3). Works also w/o _me, but I'm just following the link's suggestion.
B4X:
'Class module
Sub Class_Globals
   
End Sub

'Initializes the object. You can add parameters to this method if needed.
Public Sub Initialize
   Dim obj As JavaObject = Me
   obj.RunMethod("StartJava", Null)
End Sub

Sub callback_me()
   Log("in callback")
End Sub

#if java
import anywheresoftware.b4a.keywords.Common;
public void StartJava() {
   ba.raiseEventFromUI(this, "callback_me");
}
#End If
 
Upvote 0
Top