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:
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:
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

  • JavaObject.zip
    10.3 KB · Views: 1,787
Last edited:

Theera

Well-Known Member
Licensed User
Longtime User
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:
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:

Erel

B4X founder
Staff member
Licensed User
Longtime User
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:
BluetoothAdapter.getDefaultAdapter().getName();
Now instead of writing:
B4X:
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:
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:
AddPermission(android.permission.BLUETOOTH)
RunMethodJO is similar to RunMethod. It returns a JavaObject instead of Object.
GetFieldJO also returns JavaObject.
 

moster67

Expert
Licensed User
Longtime User
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?
 

moster67

Expert
Licensed User
Longtime User
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:
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:
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
 

Adrian Jansen

Member
Licensed User
Longtime User
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:
BluetoothAdapter.getDefaultAdapter().getName();
Now instead of writing:
B4X:
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:
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:
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
 

Adrian Jansen

Member
Licensed User
Longtime User
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.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
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:
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:
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:

rhochzwei

Member
Licensed User
Longtime User
Hi Erel,
I am trying to use "android.view.View.OnSystemUiVisibilityChangeListener" like this
B4X:
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:
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" ?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Can you post the error message?

Seems to work fine here:
B4X:
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