Lachlan just posted a link to a post on Google+ (also available as a PDF) demonstrating how to call Java from Delphi XE5.
I was shocked at both the amount and the nature of the code involved. It is long, convoluted and ugly stuff (nb. that isn’t a criticism of Paul’s code; such techniques rarely if ever result in elegant solutions) indeed sometimes requiring you to resort to using tools to reverse engineer the Java code. Certainly not for the faint hearted.
In Oxygene things are much simpler because when compiling with Oxygene for Java, Oxygene code is Java code, it’s just not written in the Java language.
The Comparison
Paul Foster’s post ends with an example of calling a getIntValue and setIntValue method on some Java class that he wrote to test the technique. For the purposes of providing a more convenient, side-by-side comparison I hope he doesn’t mind if I reproduce that last snippet here:
var jLoadedClassID,jLoadedObjectID:JNIObject; jGetMethod,jSetMethod:JNIMethodID; JavaEnv:PJNIEnv; jiReturnedValue:JNIInt; jvValuetoSet:JNIValue; begin {...donβt forget the other bits first!} jiReturnedValue:=JavaEnv^.CallIntMethodA(JavaEnv, jLoadedObjectID,jGetMethod); jvValuetoSet.i:=1234567890; JavaEnv^.CallVoidMethodA(JavaEnv, jLoadedObjectID, jSetMethod,@jvValuetoSet); end;
As you can see, this isn’t complete – there’s pre-amble needed to make all this work and I encourage you to read his article in full to appreciate just how much and what is involved.
By contrast, here’s the Oxygene code that achieves the same:
var loadedObject: MyJavaClass; returnedValue: Integer; begin // get the reference to loadedObject from somewhere ... returnedValue := loadedObject.getIntValue; loadedObject.setIntValue(1234567890); end;
Or, if you prefer to take advantage of the fact that Oxygene recognises that get/set methods can be treated as properties, and prefer the more Pascal-like syntax this permits:
returnedValue := loadedObject.IntValue; loadedObject.IntValue := 1234567890;
Important Firsts
Oxygene for Java is just one part of Oxygene product. When you purchase Oxygene you get:
- Oxygene for .NET (supports Windows RT)
- Oxygene for Java (and therefore, but not only, Android)
- Oxygene for Cocoa (OS X and iOS)
In each case, the language is a first-class citizen of each platform, allowing you to learn new, portable skills on those platforms, taking full advantage and make full use of each platform’s capabilities using the platform SDK’s directly.
Oxygene for Cocoa has supported iOS 7 since Apple started shipping the beta SDK to developers.
Oxygene for Android will support Kit-Kat as soon as Google starts shipping the SDK.
If you enjoy Pascal and enjoy firsts, it’s hard to beat being one of the first developers able to target new platforms using your favoured language.
Not Cheap, But Certainly Affordable
A subscription to Oxygene, including all of the above, costs just $699 ($599 cross-grade offer for existing Delphi users) with annual renewals of just $499 thereafter.
The Oxygene command line compiler is free.
As is a 30-day trial, if you are interested to take a look.
Jolyon, I always enjoy your posts when they show how easy something is in Oxygene. And I appreciate what is technically possibly in contrast to ‘true native’ so-called ‘solutions’.
But even I – and you know I was active for RemObjects a few years ago and still like the approach of Oxygene (and I *love* what will come up next) – even I must admit that the last part of this post is overly aggressive advertising.
This strongly leads to the the perception that you are involved in the company (which isn’t true as far as I know?).
My opinion is, that if you want to do Oxygene a favour, stop advertising it as strong as you just did. Just make the first mention of Oxy a link to the RO Product page.
If you want to talk about Oxygenes .NET / iOS / OS X capabilities, then do it in appropriate amounts in posts dedicated to that platform.
And you already did a price comparison post, so just leave it with that – or do another one, where you compare European (especially Spanish and German) prices. That’d be funny π
What I want to say is: Just to do yourself and Oxygene a favour, keep technical posts technical.
Sebastian – although the post contained some technical content (though not anything I haven’t already covered), the structure of the post was a deliberate reflection of a recent post by a certain VP at Embarcadero who shall remain nameless who similarly closed with a sales pitch of loosely related info and a link to a trial edition (admittedly he didn’t mention pricing but that was probably simply out of embarrassment or a recognition that to do so would do more harm than good in the case of Delphi π )
My tongue was placed firmly in cheek throughout the entire post. Don’t worry. I fully intend to remain focussed on the technical aspects of Oxygene. π
But thanks for the concern. π
Well, this posts of yours is not technical. Well, except 2(two!) lines of code. Paul could omit the “preamble” – he just written them all in his article. But you did not. Without showing and comparing how easy/hard is to DEPLOY custom apk and FIND it and load a class from it, you article is but void
You truly seems too enamored with Oxygene and fails to make objective comparisons.
The only “pre-amble” in Paul’s snippet that I omitted was obtaining a reference to an existing instance of a Java class, or demonstrating creating a new instance of such a class. I don’t think he showed declaring his Java class, only how to dig through the murky layers between it and FireMonkey to get at it. But here’s the declaration of a possible implementation of a MyJavaClass in Oxygene that satisfies his example:
And to instantiate in Oxygene:
that is not what Paul did..
this is what in Delphi is
type TMYClass = class … end;
loadedObject := TMyClass.Create;
Not a single line longer than your code above.
So, if you want to compare with Paul, the nyou have to do what he did:
1) find an APK – by file name
2) load an unknown non-declared class from it – by class name given as string
3) create an object of that type
4) access it’s property by name
Fair enough, I shall look into doing just that.
Okay, after “ranting” about your advertising in a separate comment, I’d like to go technical. π
PLEASE, write another post – or extend this one – and show what is involved to do this from your sample:
// get the reference to loadedObject from somewhere …
In Delphi vs. what is involved for exactly the same thing (=creating an instance of a Java object) in Oxygene.
Well, that’s rather difficult since MyJavaClass is an entirely theoretical class.
But in the case of creating an entirely new instance of that class for example, this will do the job assuming that MyJavaClass has a parameterless constructor available:
Is that what you meant ? π
It’s also worth mentioning that Brian Long is apparently going to introduce a much simpler method in his upcoming CodeRage presentation.
It could be interesting to see just how much simpler.
Hi Jolyon,
nice post.
I would like to suggest you to do an overview about “Pascal with native Android controls” See at http://blog.naver.com/simonsayz
It consists in a set of Java classes, used as glue to the Android platform,
accessed via JNI from a Free Pascal compiler 2.71.
It creates small .apk file: only 180 KB.
I don’t have time (or, it has to be said, the inclination) to cover FreePascal. When it “went 1.0” I did take a fresh look and though it had improved a lot since my previous experiences it still wasn’t enough to keep me coming back for more.
It looks interesting but I’m afraid I shall have to leave FreePascal to others to cover. π
I would like to point out, in my defense π
I was tasked with loading the Java class, I ended up deciding to try this *without* having the class defined in my delphi code – simply because I could see the limits of the current JNI implementation. There are a more than a few uses for this approach, but for general Java code sharing and reuse – where you know the java class designs at the time of writing the delphi code, then Brian Long (as someone else mentioned in the comments) has a *much* nicer solution for importing the java class and calling it using more conventional methods – in fact it looks very much the same as the current JNI bridge implementation and more like Jolyons example. I can only hope that Brians code gets added to the JNI Bridge in a patch (or more likely to XE6) and voice my disappointment that this kind of maneuver wasn’t covered by the released code (much like the ability to inherit from a Java class and thus work with Broadcast receivers with ease).
Jolyon is merely attempting to point out that XE5 is far from the only solution to the problem of targeting Android with a language that isn’t C++ or Java (which are not as nice to work in as Delphi/Object Pascal) – for those interested in the actual Java implementation and a more “worked” example, see this link here http://www.pclviewer.com/android/androidJNI.html – which my boss put up to fill in the other details – he also helpfully demonstrates passing multiple parameters through the JNI bridge to the java class.