B4A Library JavaObject library

Discussion in 'Additional libraries, classes and official updates' started by Erel, Nov 14, 2013.

  1. Erel

    Erel Administrator Staff Member Licensed User

    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:
    Code:
    Dim jLabel As JavaObject = Label1 'wrap the Label object
    jLabel.RunMethod("setPadding"Array As Object(10dip10dip10dip10dip))
    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:
    Code:
    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.
     

    Attached Files:

    Last edited: Jul 11, 2016
    Sandman, eps, jazzzzzzz and 16 others like this.
  2. klaus

    klaus Expert Licensed User

    Looks interesting. Just tried it in a project.
    Is there any advantage using JavaObject instead of Reflection apart the simpler syntax.
     
  3. Erel

    Erel Administrator Staff Member Licensed User

    No. Only the simpler syntax.

    Note that this library will also be compatible with B4J.
     
  4. Informatix

    Informatix Expert Licensed User

    I love this new lib! My code using reflection is now easier to read and easier to maintain.
    :)
     
  5. alwaysbusy

    alwaysbusy Well-Known Member Licensed User

    Very usefull. Thx!
     
  6. Theera

    Theera Well-Known Member Licensed 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?
    Code:
    Dim obj1 as Reflector
    obj1.Target=Label1
    obj1.RunPublicmethod (
    "SetPadding",Array As Object(10dip10dip10dip10dip), 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: Nov 15, 2013
  7. JakeBullet70

    JakeBullet70 Well-Known Member Licensed User

    Oh I like this! Thanks!
     
  8. Erel

    Erel Administrator Staff Member Licensed User

    @Theera the equivalent Reflection code is:
    Code:
    obj1.RunPublicmethod ("SetPadding",ArrayAsObject(10dip10dip10dip10dip), ArrayAsString("java.lang.int", _
     
    "java.lang.int""java.lang.int""java.lang.int"))
     
    Theera likes this.
  9. RayLee

    RayLee Member Licensed User

    It's so smart~ :)
    If add SetListener method, it will be pretty good!

    Happy new year!
     
  10. Erel

    Erel Administrator Staff Member Licensed 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:
    Code:
    BluetoothAdapter.getDefaultAdapter().getName();
    Now instead of writing:
    Code:
    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:
    Code:
    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:
    Code:
    AddPermission(android.permission.BLUETOOTH)
    RunMethodJO is similar to RunMethod. It returns a JavaObject instead of Object.
    GetFieldJO also returns JavaObject.
     
    stevel05 likes this.
  11. moster67

    moster67 Well-Known Member Licensed User

    Erel,

    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?
     
  12. Erel

    Erel Administrator Staff Member Licensed User

    It should have been included. I will upload it to the first post.
     
  13. moster67

    moster67 Well-Known Member Licensed 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.basic4ppc.com/android/forum/threads/tag-cloud.35707/#content) which requires the JavaObject-library but I get an error:

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

    Code:
    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
     
  14. Erel

    Erel Administrator Staff Member Licensed User

    The TabCloud may need to be recompiled with the new version as this update changed the return type of InitializeStatic.
     
    moster67 likes this.
  15. Adrian Jansen

    Adrian Jansen Member Licensed User

    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
     
  16. Erel

    Erel Administrator Staff Member Licensed User

    Can you post the full error message from the logs?
     
  17. Adrian Jansen

    Adrian Jansen Member Licensed 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.
     
  18. Erel

    Erel Administrator Staff Member Licensed 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
    Code:
    Sub Activity_Create(FirstTime As Boolean)
      
    Dim b As Button
      b.Initialize(
    "")
      
    Activity.AddView(b, 00200dip200dip)
      
    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

    Code:
    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: Apr 3, 2014
  19. rhochzwei

    rhochzwei Member Licensed User

    Hi Erel,
    I am trying to use "android.view.View.OnSystemUiVisibilityChangeListener" like this
    Code:
    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 :
    Code:
    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" ?
     
    avacondios likes this.
  20. Erel

    Erel Administrator Staff Member Licensed User

    Can you post the error message?

    Seems to work fine here:
    Code:
    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
     
Loading...