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,143
Last edited:

Rick Harris

Well-Known Member
Licensed User
Kindly update the JavaObject.zip file in thread #1 to the latest version 2.01 or higher (including both the XML and JAR files). I had to re-install B4A and now have lost version 2.01 and don't know anymore where to find it.
The latest version is needed to use commands like: jo.InitializeContext
 

Rick Harris

Well-Known Member
Licensed User
I've uploaded v2.05 to the first post.
Thank you very much indeed! At least this is something positive after a weekend with heaps of problems with newer versions of the Android SDK. In the end I had to restore Windows to at least get B4A working again.

May I suggest that in thread #1 you make it clear that the ZIP file contains JavaObject 2.05. As it reads now, everyone would think that it is the old version 1.20.
 

Erel

B4X founder
Staff member
Licensed User
Thank you very much indeed! At least this is something positive after a weekend with heaps of problems with newer versions of the Android SDK. In the end I had to restore Windows to at least get B4A working again.
As I wrote to you in another thread, you are using an old version of B4A. Upgrade to the latest version and it will work with the latest version of Android SDK.

As it reads now, everyone would think that it is the old version 1.20.
I will update it. JavaObject is part of the preinstalled libraries for quite a long time so most developers already use the latest version.
 

Rick Harris

Well-Known Member
Licensed User
As I wrote to you in another thread, you are using an old version of B4A. Upgrade to the latest version and it will work with the latest version of Android SDK.


I will update it. JavaObject is part of the preinstalled libraries for quite a long time so most developers already use the latest version.
OK, I see. For some time I have been planning to update my B4A from versie 3.82 to 6.00, but in view of the awful problems I had with recent Android SDK versions, I have postponed it. I hate Windows-10 (with all its spyware and malware) so I still develop on a Windows-XP machine (not good, I know but all my VB6 and other developer stuff is also on that machine).
 

KY Leng

Member
Licensed User
Good morning,

I install "Network Cell Info Lite" and it work fine. However, when I want to do it with B4A using JavaObject, the result is not correct.
Below is my code:

B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
   
    Dim css, jo As JavaObject
    Dim result As String

    css = jo.InitializeNewInstance("android.telephony.CellSignalStrengthLte",Null)
    Log("Object Test result: "  & css)
    result= css.RunMethod("hashCode",Null)
    Log("hashCode: "  & result)
    result= css.RunMethod("getDbm",Null)
    Log("Signal Strength as dBm: "  & result)
    result= css.RunMethod("getLevel",Null)
    Log("Signal level as an int from [0..4]: "  & result) 
    result= css.RunMethod("getAsuLevel",Null)
    Log("Signal level as an asu value between [0..31]: "  & result)   
   
    css = jo.InitializeNewInstance("android.telephony.CellIdentityLte",Null)
    Log("Object Test result: "  & css)   
    result= css.RunMethod("hashCode",Null)
    Log("hashCode: "  & result)
    result= css.RunMethod("getMcc",Null)
    Log("MCC: "  & result)
    result= css.RunMethod("getMnc",Null)
    Log("MNC: "  & result)
    result= css.RunMethod("getPci",Null)
    Log("PCI: "  & result)
    result= css.RunMethod("getTac",Null)
    Log("TAC: "  & result)   
    result= css.RunMethod("getCi",Null)
    Log("CI: "  & result)
   
End Sub

And the result after compile look like this:

Object Test result: (CellSignalStrengthLte) CellSignalStrengthLte: ss=2147483647 rsrp=2147483647 rsrq=2147483647 rssnr=2147483647 cqi=2147483647 ta=2147483647
hashCode: -186
Signal Strength as dBm: 2147483647
Signal level as an int from [0..4]: 0
Signal level as an asu value between [0..31]: 97
Object Test result: (CellIdentityLte) CellIdentityLte:{ mMcc=2147483647 mMnc=2147483647 mCi=2147483647 mPci=2147483647 mTac=2147483647}
hashCode: -2119808802
MCC: 2147483647
MNC: 2147483647
PCI: 2147483647
TAC: 2147483647
CI: 2147483647


Do I miss something ?
Best regards,
 
Last edited:

KY Leng

Member
Licensed User
1. Please use [code]code here...[/code] tags when posting code.
2. Please start a new thread for this question.

If you can tell us where we can find the Java Code and How the Java Code can be call in B4A, I think we don't need to bother you again... Please forgive me, I cannot find the tutorial related to this or in-line Java code that is easy to understand... If we know Java well, no need to use B4A, right ?
 

JordiCP

Well-Known Member
Licensed User
Do I miss something ?
Best regards,

Your Java code looks correct, and the results make sense. Everything is described in the android documentation

According to https://developer.android.com/reference/android/telephony/CellIdentityLte.html ,
B4X:
int getMnc()
Returns:
2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
(and the value 2147483647 that you are obtaining is INTEGER.MAX_VALUE, so it is unknown)


Also, this log
"Signal level as an asu value between [0..31]: 97"
is incorrect, since documentation in , https://developer.android.com/reference/android/telephony/CellSignalStrengthLte.html#getAsuLevel() says
B4X:
int getAsuLevel ()
Get the LTE signal level as an asu value between 0..97, 99 is unknown Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
, so 97 is also a valid value.


Then, if the app reports different values on the same device (and under the same conditions), perhaps you are addressing the wrong classes or the app is using a non-official API. Are you connected to LTE?
You could try with android.telephony.CellIdentityGSM, android.telephony.CellIdentityWCDMA, .... and android.telephony.CellSignalStrengthWCDMA, ...... perhaps the app is choosing which is the appropiate one according to the visible networks type
 

KY Leng

Member
Licensed User
Your Java code looks correct, and the results make sense. Everything is described in the android documentation

According to https://developer.android.com/reference/android/telephony/CellIdentityLte.html ,
B4X:
int getMnc()
Returns:
2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
(and the value 2147483647 that you are obtaining is INTEGER.MAX_VALUE, so it is unknown)


Also, this log
"Signal level as an asu value between [0..31]: 97"
is incorrect, since documentation in , https://developer.android.com/reference/android/telephony/CellSignalStrengthLte.html#getAsuLevel() says
B4X:
int getAsuLevel ()
Get the LTE signal level as an asu value between 0..97, 99 is unknown Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
, so 97 is also a valid value.


Then, if the app reports different values on the same device (and under the same conditions), perhaps you are addressing the wrong classes or the app is using a non-official API. Are you connected to LTE?
You could try with android.telephony.CellIdentityGSM, android.telephony.CellIdentityWCDMA, .... and android.telephony.CellSignalStrengthWCDMA, ...... perhaps the app is choosing which is the appropiate one according to the visible networks type

Thank you very much JordiCP for the response.
However, I already verify my mobile service, it is 4G.
Moreover, if I use below code, it give me the result, just don't have Earfcn that I want.
B4X:
Sub Get_Cell_Info
    '----------------------------------------------------------------------------------
   
    Dim telMgr As JavaObject = GetContext.RunMethod("getSystemService", Array("phone"))
    Dim Cell As String
    Dim Pos1, Pos2 As Int 
   
    Try       
        Dim OperatorName As String = telMgr.RunMethod("getNetworkOperatorName", Null)   
        Log("> NetworkOperatorName: " & OperatorName)
        
        Dim DataNetworkType As Int = telMgr.RunMethod("getDataNetworkType", Null)   
        Log("> DataNetworkType: " & DataNetworkType)
        
        Dim CellLocation As String = telMgr.RunMethod("getCellLocation", Null)   
        Log("> CellLocation: " & CellLocation)
       
        Dim LstCellInfo As List = telMgr.RunMethod("getAllCellInfo", Null)   
        If (LstCellInfo.Size > 0) Then    
            Cell = LstCellInfo.Get(0)
            Log("> Main Cell.Infor=" & Cell)
        End If
    Catch
        Log(LastException.Message)
        ToastMessageShow(LastException.Message, True)
    End Try
    '----------------------------------------------------
End Sub

Sub GetContext As JavaObject
  Return GetBA.GetField("context")
End Sub

Sub GetBA As JavaObject
  Dim jo As JavaObject
  Dim cls As String = Me
  cls = cls.SubString("class ".Length)
  jo.InitializeStatic(cls)
  Return jo.GetFieldJO("processBA")
End Sub

And the result look like below for LTE:

> Main Cell.Infor=CellInfoLte:{mRegistered=YES mTimeStampType=oem_ril mTimeStamp=2605340075290ns CellIdentityLte:{ mMcc=520 mMnc=18 mCi=64812801 mPci=471 mTac=3101 mEarfcn=0} CellSignalStrengthLte: ss=24 rsrp=-99 rsrq=-4 rssnr=21 cqi=15 ta=2}

and my Android is version 7 already that is why I can see the field mEarfcn but it is always 0.

Looking forward to hearing from the group soon...
 
Status
Not open for further replies.
Top