B4A Library JavaObject library

Status
Not open for further replies.
The purpose of JavaObject library is similar to the purpose of Reflection library. Both libraries allow you to directly call Java APIs based on Java reflection features.

JavaObject design is different than Reflection library and in most cases simpler to use. However JavaObject doesn't replace Reflection library as it doesn't support all of its features. In many cases you can use both libraries together (both are lightweight libraries).

JavaObject approach is more "object oriented". You declare a JavaObject object which then "wraps" any other object and provide three methods: SetField, GetField and RunMethod.

JavaObject variable is similar to an Object variable with the addition of the reflection methods.

For example to set the padding of a view:
B4X:
Expand Collapse Copy
Dim jLabel As JavaObject = Label1 'wrap the Label object
jLabel.RunMethod("setPadding", Array As Object(10dip, 10dip, 10dip, 10dip))
Note that you do not need to specify the parameters types. However the types should be the exact types. The call will fail if you pass a double instead of an int.

One exception is that you can pass a string instead of Enum.

There are also two Initialize methods.
InitializeStatic - Use this method when you want to call a static method or access a static field.

For example this code calls the static Bitmap.createScaledBitmap method:
B4X:
Expand Collapse Copy
Sub CreateScaledBitmap(Original As Bitmap, Width As Int, Height As Int) As Bitmap
  Dim bo As JavaObject
  bo.InitializeStatic("android.graphics.Bitmap")
  Dim bmp As Bitmap = bo.RunMethod("createScaledBitmap", Array As Object(Original, Width, Height, False))
  Return bmp
End Sub

InitializeNewInstance - Creates a new instance of the given class with the given parameters (or Null)


Notes
- JavaObject can only access public methods and fields (unlike Reflection library).
- JavaObject doesn't include the helper methods to access the context and other fields as in Reflection library. You can use both libraries together when these fields are needed.
- There is almost no overhead for a JavaObject instance. It is better to create multiple JavaObjects instead of reusing a single instance.

V2.05 is attached.
 

Attachments

Last edited:
Hi Erel,
I'm not good at programming, I try use reflection Library to compare with the example which using a new library. I'm not sure is right?
B4X:
Expand Collapse Copy
Dim obj1 as Reflector
obj1.Target=Label1
obj1.RunPublicmethod ("SetPadding",Array As Object(10dip, 10dip, 10dip, 10dip), Array As String("java.lang.int"))

P.S. I need to compare in order to see different. (I would like save as my website)
 
Last edited:
JavaObject v1.00 is now included in B4A and B4J.

This update makes it easier to chain method calls and fields.

For example, if you want to get the name of the Bluetooth device, you can use this Java code:
B4X:
Expand Collapse Copy
BluetoothAdapter.getDefaultAdapter().getName();
Now instead of writing:
B4X:
Expand Collapse Copy
Dim jo As JavaObject
jo.InitializeStatic("android.bluetooth.BluetoothAdapter")
Dim jo2 As JavaObject = jo.RunMethod("getDefaultAdapter", null)
Return jo2.RunMethod("getName", null)
You can write:
B4X:
Expand Collapse Copy
Dim jo As JavaObject
Return jo.InitializeStatic("android.bluetooth.BluetoothAdapter").RunMethodJO("getDefaultAdapter", Null) _
    .RunMethod("getName", Null)
Note that you need to add the following line to the manifest editor for the above code to work:
B4X:
Expand Collapse Copy
AddPermission(android.permission.BLUETOOTH)
RunMethodJO is similar to RunMethod. It returns a JavaObject instead of Object.
GetFieldJO also returns JavaObject.
 
Erel,

JavaObject v1.00 is now included in B4A and B4J.

I think that in the beta (3.20 - Beta 3) the JavaObject-library is not included. Perhaps you meant that it will be included in the final release of B4A?
 
Using 3.20 - beta 3:
Hmm, I downloaded the library from this thread and put in my additional-library folder (B4A). Then I was trying out Stevel05's TagCloud-project (http://www.b4x.com/android/forum/threads/tag-cloud.35707/#content) which requires the JavaObject-library but I get an error:

B4X:
Expand Collapse Copy
java.lang.NoSuchMethodError: anywheresoftware.b4j.object.JavaObject.InitializeStatic
    at b4a.example.slcolorlut._setcolors(slcolorlut.java:177)
    at b4a.example.slcolorlut._initialize(slcolorlut.java:166)
    at com.stevel05.main._activity_create(main.java:280)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:170)
    at com.stevel05.main.afterFirstLayout(main.java:98)
    at com.stevel05.main.access$100(main.java:16)
    at com.stevel05.main$WaitForLayout.run(main.java:76)
    at android.os.Handler.handleCallback(Handler.java:725)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:5306)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
    at dalvik.system.NativeStart.main(Native Method)

In the error-report, the first line:

B4X:
Expand Collapse Copy
anywheresoftware.b4j.object.JavaObject.InitializeStatic

refers to a b4j.object? Could this be the error? Are there different versions for B4A and B4J?

EDIT: just saw your reply. I tested with version 0.9
 
JavaObject v1.00 is now included in B4A and B4J.

This update makes it easier to chain method calls and fields.

For example, if you want to get the name of the Bluetooth device, you can use this Java code:
B4X:
Expand Collapse Copy
BluetoothAdapter.getDefaultAdapter().getName();
Now instead of writing:
B4X:
Expand Collapse Copy
Dim jo As JavaObject
jo.InitializeStatic("android.bluetooth.BluetoothAdapter")
Dim jo2 As JavaObject = jo.RunMethod("getDefaultAdapter", null)
Return jo2.RunMethod("getName", null)
You can write:
B4X:
Expand Collapse Copy
Dim jo As JavaObject
Return jo.InitializeStatic("android.bluetooth.BluetoothAdapter").RunMethodJO("getDefaultAdapter", Null) _
    .RunMethod("getName", Null)
Note that you need to add the following line to the manifest editor for the above code to work:
B4X:
Expand Collapse Copy
AddPermission(android.permission.BLUETOOTH)
RunMethodJO is similar to RunMethod. It returns a JavaObject instead of Object.
GetFieldJO also returns JavaObject.

I tried both versions of the above, and got a java runtime error:
"An error has occurred in sub:java.lang.reflect.InvocationTargetException"
Same for two phones, one running Android 2.3, and also 4.2.

Any comments would be appreciated
 
Thanks Erel,

I had logging turned off, since I was using the test program to turn both Bluetooth and WiFi on and off. But when I stripped the program down and removed the PhoneStateListener and Reflection libraries, it all worked correctly on your example. Now to add that stuff back in, and find out what actually triggers the problem.
 
V1.20 is an important update. It adds support for dynamic implementation of interfaces. This means that you can use JavaObject to bind new types of events at runtime.

Example of binding OnTouchListener to a Button, the interface is described here: http://developer.android.com/reference/android/view/View.OnTouchListener.html
B4X:
Expand Collapse Copy
Sub Activity_Create(FirstTime As Boolean)
  Dim b As Button
  b.Initialize("")
  Activity.AddView(b, 0, 0, 200dip, 200dip)
  Dim jo As JavaObject = b
  Dim e As Object = jo.CreateEventFromUI("android.view.View.OnTouchListener", "btouch", False)
  jo.RunMethod("setOnTouchListener", Array As Object(e))
End Sub

Sub btouch_Event (MethodName As String, Args() As Object) As Object
  Dim motion As JavaObject = Args(1) 'args(0) is View
  Dim x As Float = motion.RunMethod("getX", Null)
  Dim y As Float = motion.RunMethod("getY", Null)
  Log(x & ", " & y)
  Return True
End Sub

Example of MediaScannerConnection.scanFile with implementation of OnScanCompletedListener: http://developer.android.com/refere...cannerConnection.OnScanCompletedListener.html

B4X:
Expand Collapse Copy
Sub Activity_Create(FirstTime As Boolean)
   Dim MediaScanner As JavaObject
   MediaScanner.InitializeStatic("android.media.MediaScannerConnection")
   'Create the interface
   Dim e As Object = MediaScanner.CreateEvent("android.media.MediaScannerConnection.OnScanCompletedListener", "scan", Null)
   MediaScanner.RunMethod("scanFile", Array As Object(GetContext, _
     Array As String(File.Combine(File.DirRootExternal, "1.jpg")), _
     Null, _
     e))
End Sub

Sub scan_Event (MethodName As String, Args() As Object) As Object
   Log("Path = " & Args(0))
   Log("Uri = " & Args(1))
   Return False
End Sub

Sub GetContext As Object
   Dim jo As JavaObject = Activity
   Return jo.RunMethod("getContext", Null)
End Sub

Note that there are two methods to create events: CreateEvent and CreateEventFromUI. CreateEventFromUI is similar to ba.raiseEventFromUI. It sends the event message to the internal message queue. Many UI events can be paused (with the debugger or a modal dialog) by sending the event to the message queue the event sub is executed after the original event has already completed.

Note that events fired from different threads will be delegated to the main thread automatically.
 
Last edited:
Hi Erel,
I am trying to use "android.view.View.OnSystemUiVisibilityChangeListener" like this
B4X:
Expand Collapse Copy
Sub Activity_Create(FirstTime As Boolean)
   Dim jo As JavaObject = Activity
   Dim e As Object = jo.CreateEvent("android.view.View.OnSystemUiVisibilityChangeListener", "VisibilityChanged", Null)
   jo.RunMethod("setOnSystemUiVisibilityChangeListener", Array As Object(e))

but the compiler says "Syntax error" for the following code line :
B4X:
Expand Collapse Copy
Dim e As Object = jo.CreateEvent("android.view.View.OnSystemUiVisibilityChangeListener", "VisibilityChanged", Null)
and I don't know why?

What is the Sub for the "VisibilityChange Event" ?
 
Can you post the error message?

Seems to work fine here:
B4X:
Expand Collapse Copy
Sub Activity_Create(FirstTime As Boolean)
  Dim jo As JavaObject = Activity
  Dim e As Object = jo.CreateEvent("android.view.View.OnSystemUiVisibilityChangeListener", "VisibilityChanged", Null)
  jo.RunMethod("setOnSystemUiVisibilityChangeListener", Array As Object(e))
 End Sub
 
Status
Not open for further replies.
Top