Android Question Correct way to create a "Dim" from Java classes without parameterless constructors?

aedwall

Active Member
Licensed User
Longtime User
I have 3rd party .java files that I know work using Java on my desktop. I have managed to create a library using them and most of the functions work. But there are a couple of .java files (classes?) that require parameters sent to them. I am ignorant about Java and constructors and other "fancy" stuff.

When I use B4x Object Browser, I see this:

initTCPlanetIntern

Type
Method
Description

Syntax
initTCPlanetIntern(sw As SwissEph, planet As int, flags As int, offset As double, precalcCount As int, precalcSafetyfactor As double)

Return Value
void

I need to do whatever it takes in order to be able to call the TCPlanet class and have it execute what it does.

Doing this:

Dim tc0 As JavaObject
tc0.InitializeArray("anywheresoftware.b4a.sample1.TCPlanet", Array(swe1, 1, 128*1024, 120)) 'planet, flags, 120

brings an error:

Installing file.
PackageAdded: package:anywheresoftware.b4a.xxxxx
:null,0
java.lang.InstantiationException: java.lang.Class<anywheresoftware.b4a.sample1.TCPlanet> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
at anywheresoftware.b4a.shell.Shell.createObject(Shell.java:578)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:354)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
at anywheresoftware.b4a.helen.main.afterFirstLayout(main.java:95)
at anywheresoftware.b4a.helen.main.access$000(main.java:17)
at anywheresoftware.b4a.helen.main$WaitForLayout.run(main.java:80)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
:null,0
java.lang.RuntimeException: Unexpected command: 97
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:414)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:246)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:134)
at anywheresoftware.b4a.helen.main.afterFirstLayout(main.java:95)
at anywheresoftware.b4a.helen.main.access$000(main.java:17)
at anywheresoftware.b4a.helen.main$WaitForLayout.run(main.java:80)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **


Can someone tell me what to do to make this work?

The TCPlanet.java file looks like this:

package anywheresoftware.b4a.sample1;

import anywheresoftware.b4a.BA.ShortName;

@ShortName("TCPlanet")

public class TCPlanet extends TransitCalculator
{

// private void initTCPlanetIntern(SwissEph sw, int planet, int flags, double offset)
// {
// this(sw, planet, flags, offset, 200, 1.4);
// }

public TCPlanet()
{
}

//public void initTCPlanet(int planet, int flags, double offset)
//{
// initTCPlanetIntern(null, planet, flags, offset);
//}

public void initTCPlanetIntern(SwissEph sw, int planet, int flags, double offset, int precalcCount, double precalcSafetyfactor)
{
// Check parameter: //////////////////////////////////////////////////////
// List of all valid flags:
this.tflags = flags;

etc.
}

Thank you.
 

stevel05

Expert
Licensed User
Longtime User
Did you wrap the java? as the code looks like it's already wrapped for B4a. If you compiled the jar file, you should have created (or it would have been created if you used the Simple Library Compiler) an xml from the javadocs at the same time, in which case there should be no need to use JavaObject to access its methods.

Just in case, and perhaps save a bit of time, if you do need to access it with a JavaObject, then you need to initialize it with the InitializeNewInstance method and pass the required parameters in an Object array.
 
Upvote 0

aedwall

Active Member
Licensed User
Longtime User
I'm sorry, but I have no idea what "wrap the Java" means. I modified the .java code so that it could make the library for b4a. The library was made successfully. Now I just have to set up the code that allows me to initialize and use the TCPlanet class. Yes, I made the .xml file, but apparently because of "constructors", the library doesn't show the methods for TCPlanet (because of the way it is constructed). That is why I am trying to "reconstruct" things in order that b4a sees what is actually in the library.

>> Just in case, and perhaps save a bit of time, if you do need to access it with a JavaObject, then you need to initialize it with the InitializeNewInstance method and pass the required parameters in an Object array.

Yes, that is what I am trying to do. I thought that from the code I provided that someone who knew what they were doing could do that for me - I have spent hours on trying to understand this and so far have little to show for it. To me Java is needlessly complicated and it is a hostile environment in which to work. But that's only an uneducated opinion.

Apparently I need to do both of these .InitializeArray and then .InitializeNewInstance. But I can;t even get the .InitializeArray to work, much less .InitializeNewInstance.

Thank you.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
I don't see why you would need to run initializeArray, that does what it says it does and creates an array.

Without seeing all of the code it is difficult to say whether it is usable or not. Just the method name 'initTCPlanetIntern' implies that it expects to be an internal initialization and may include code that precludes it's direct call.

If you try
B4X:
Dim Planet As Int = 1
Dim Flags As Int = 128*1024
Dim OffSet As Double = 120
Dim PreCalcCount As Int = ? an appropriate value
Dim PreCalcSafetyFactor As Double = ? an appropriate value

Dim tc0 As JavaObject
tc0.InitializeNewInstance("anywheresoftware.b4a.sample1.TCPlanet")
tc0.RunMethod("initTCPlanetIntern", Array(swe1, Planet, Flags, Offset, PreCalcCount, PreCalcSafetyfactor))

Assuming that swe1 is of type SwissEph or a JavaObject of that type.


Additionally, judging from the code you supplied the method you are trying to call is commented out, so you will also need to supply values for precalcCount and precalcSafetyfactor making sure they are of the appropriate type.

You would probably do better to get the Library working correctly and not have to use JavaObject to access it.
 
Upvote 0

aedwall

Active Member
Licensed User
Longtime User
Let me try again to explain things. Here is what I have in "TCPlanet.java":

B4X:
package anywheresoftware.b4a.sample1;
import anywheresoftware.b4a.BA.ShortName;
@ShortName("TCPlanet")

/**
* This class implements a TransitCalculator for one planet's position or speed.<p>
* You would create a TransitCalculator from this class and use the SwissEph.getTransit() methods to
* actually calculate a transit, e.g.:<p>
* SwissEph sw = new SwissEph(...);
*
* int flags = SweConst.SEFLG_SWIEPH |
*             SweConst.SEFLG_TRANSIT_LONGITUDE |
*             SweConst.SEFLG_TRANSIT_SPEED;
*
* boolean backwards = false;
*
* TransitCalculator tc = new TCPlanet(sw, 1, flags, 0);
*
* double nextTransitET = sw.getTransitET(tc, jdET, backwards);
*/
public class TCPlanet extends TransitCalculator implements java.io.Serializable
{
  public TCPlanet(SwissEph sw, int planet, int flags, double offset)
  {
    this(sw, planet, flags, offset, 200, 1.4);
  }

  public TCPlanet(SwissEph sw, int planet, int flags, double offset, int precalcCount, double precalcSafetyfactor)
  {
    //more code
  }
}

I can't seem to call the "TCPlanet class and have it recognized. I have defined this: Public swe1 As SwissEph

I just want to call the "sw.getTransitET" method and get the results back. I have tried hundreds of combinations and get various error messages, usually "java.lang.ClassNotFoundException: anywheresoftware$b4a$BA$TCPlanet". I don't understand why it does not think "TCPlanet" or "anywheresoftware.b4a.sample1.TCPlanet" or anything else I've tried is not the name of the class.

And I don't know what needs to be initialized or not. I have defined JavaObjects and everything else I can think of and nothing works. How can this be so difficult?

Can anyone please help? Thank you.
 
Last edited:
Upvote 0

aedwall

Active Member
Licensed User
Longtime User
I do this and it tells me Class Not Found:

B4X:
Dim tc0 As JavaObject

tc0.InitializeArray("anywheresoftware.b4a.BA.TCPlanet", Array(swe1, 1, 128*1024, 120))

Why?

These don't work either:

B4X:
tc0.InitializeArray("TCPlanet", Array(swe1, 1, 128*1024, 120))

tc0.InitializeArray("anywheresoftware.b4a.sample1.TCPlanet", Array(swe1, 1, 128*1024, 120))
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Please use [code]code here...[/code] tags when posting code.

JavaObject.InitializeNewInstance expects two parameters:
1. The full class name.
2. The constructor parameters.

B4X:
Dim sw As JavaObject
sw.InitializeNewInstance("full name of SwissEph", Array (<required parameters>))
Dim tcpplanet As JavaObject
tcpplanet.InitializeNewInstance("full name of TCPlanet", Array (sw, planet, flags, offset))
 
Upvote 0

aedwall

Active Member
Licensed User
Longtime User
Please use [code]code here...[/code] tags when posting code.

JavaObject.InitializeNewInstance expects two parameters:
1. The full class name.
2. The constructor parameters.

B4X:
Dim sw As JavaObject
sw.InitializeNewInstance("full name of SwissEph", Array (<required parameters>))
Dim tcpplanet As JavaObject
tcpplanet.InitializeNewInstance("full name of TCPlanet", Array (sw, planet, flags, offset))

I don't think SwissEph has any constructor parameters. What do I do then (with regard to "Array (<required parameters>)")?

I think the answer is to put "NULL" instead of "Array (<required parameters>)" (all without quotes).
 
Last edited:
Upvote 0

aedwall

Active Member
Licensed User
Longtime User
I tried a different approach after changing my package name from "anywheresoftware.b4a.sample1" to "swisseph":

I took this code and ran it with no problems:

B4X:
Dim sw AsJavaObject
sw.InitializeNewInstance("swisseph.SwissEph", NULL)

Then I changed the code to this and it bombed, "Class not found".

B4X:
Dim sw AsJavaObject
sw.InitializeNewInstance("SwissEph", NULL)

This proves that the full name of the class is "swisseph.SwissEph" and nothing else.

So then I tried to run this:

B4X:
Dim tcpplanet As JavaObject
tcpplanet.InitializeNewInstance("swisseph.TCPlanet", Array (sw, planet, flags, offset))

And I get a "Class not found" error. So why it will recognize the SwissEph class and not the TCPlanet class is beyond me.

My library .xml file shows this:

<class>
<name>swisseph.TCPlanet</name>
<shortname>TCPlanet</shortname>
<owner>process</owner>
<method>
<name>toString</name>
<returntype>java.lang.String</returntype>
</method>

and this:

<class>
<name>swisseph.SwissEph</name>
<shortname>SwissEph</shortname>
<owner>process</owner>
<method>
<name>getFixstarMagnitude</name>
<returntype>double</returntype>
<parameter>
<name>star</name>
<type>java.lang.String</type>
</parameter>
</method>

So why it can't find something and yet it finds something else, well, I don't get it.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
I had a play with the library this afternoon, downloaded from the web site. It appears that the J2ME version of the library is missing some classes. And the other one doesn't want to compile on Android. From the quick googling I did it seems that it may have been compiled with a version of Java that is too old for the Android SDK to deal with, but I'm not an expert on that so maybe you will have a better experience.

I have it working on B4J if that's any good to you.
 
Upvote 0

aedwall

Active Member
Licensed User
Longtime User
I had a play with the library this afternoon, downloaded from the web site. It appears that the J2ME version of the library is missing some classes. And the other one doesn't want to compile on Android. From the quick googling I did it seems that it may have been compiled with a version of Java that is too old for the Android SDK to deal with, but I'm not an expert on that so maybe you will have a better experience.

I have it working on B4J if that's any good to you.

Which library are we talking about? I have a v1.76 that works, and I am currently working with v2.01. I know nothing about J2ME and did not precompile the source code with that option. I am using Java SDK 1.8 and not some old version. I can run the same Java code on my desktop using java.exe and javac.exe, so I know the source code is good. What is not good is that b4a cannot recognize the TCPlanet class, even though it recognizes the SweDate and SwissEph classes.

Thank you for your help.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Is the TCPlanet class in the Jar file?
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
I initially downloaded a version with the name: swissephJ2ME-2.01.00-01.jar which is missing all of the TC* classes. I got it working on B4j with the jar file named: swisseph-2.01.00-01.jar but that won't compile on Android.

You can use JD-Gui to check what's in the jar file, or just unzip it.
 
Upvote 0

aedwall

Active Member
Licensed User
Longtime User
According to the .xml file it is. But how can I check the actual file itself? I see references to it in the .jar file when I open the .jar file in a text editor.
 
Upvote 0

aedwall

Active Member
Licensed User
Longtime User
I initially downloaded a version with the name: swissephJ2ME-2.01.00-01.jar which is missing all of the TC* classes. I got it working on B4j with the jar file named: swisseph-2.01.00-01.jar but that won't compile on Android.

You can use JD-Gui to check what's in the jar file, or just unzip it.

As explained in the documentation, J2ME version is the cut-down version without the TC* stuff. That is NOT what I am dealing with.

I attach my current library files. Well I tried to attach them, but apparently something is wrong with the upload files feature. Figures.
 
Upvote 0

aedwall

Active Member
Licensed User
Longtime User
I initially downloaded a version with the name: swissephJ2ME-2.01.00-01.jar which is missing all of the TC* classes. I got it working on B4j with the jar file named: swisseph-2.01.00-01.jar but that won't compile on Android.

You can use JD-Gui to check what's in the jar file, or just unzip it.

I unzipped with 7-zip and all the TC* files are there.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
If you want to attach it I will take a look.
 
Upvote 0

aedwall

Active Member
Licensed User
Longtime User
If you want to attach it I will take a look.

I tried but this idiotic forum software does not accept my chosen file(s). I guess it must be this silly 500KB file limit. Another pain to deal with.

Oh, gee - it worked, for once. Hallejuh. Thank you for your help.
 

Attachments

  • SE_v201 - part 1.zip
    29.2 KB · Views: 180
  • SE_v201 - part 2.zip
    499.8 KB · Views: 171
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Unfortunately there is nothing helpful in the Jar file. Just the compiled classes, no source. Did you create the xml file?
 
Upvote 0
Top