Over the past few days I posted a two part series showing how to obtain the current battery level as part of the implementation of an Android AppWidget using Oxygene. As far as I can tell AppWidgets simply aren’t possible using Delphi but reading the battery is quite straightforward Android SDK work, and I thought a comparison of the Oxygene and Delphi equivalents might be interesting.

With Oxygene you are working directly with the Java Android SDK. The code I originally found for reading the battery level was written in Java. A quick dusting of Oxygene syntax and I was done. Things proved a little less straightforward with Delphi.

For the purposes of this comparison I’ll present the relevant code in the form of a simple function – not intended to be compilable as-is in any of the languages, just to encapsulate and demonstrate the key elements.

JAVA

First, the Java ‘original’:

using
  android.content,
  android.os;

int BatteryPercent(Context context);
{
  IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
  Intent battery = context.registerReceiver(null, filter);
 
  int level := battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
  int scale := battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
 
  return ((100 * level) / scale);
}

OXYGENE

In the case of Oxygene you can also use inline variable declarations if you prefer with the added benefit of type inference, if that’s your thing. It’s not really my thing (though it may grow on me), but for the benefit of those who do appreciate such things, here’s the thoroughly modern Oxygene version:

uses
  android.content,
  android.os;

method BatteryPercent(const aContext: Context): Integer;
begin
  var filter  := new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
  var battery := aContext.registerReceiver(NIL, filter);
 
  var level := battery.IntExtra[BatteryManager.EXTRA_LEVEL, -1];
  var scale := battery.IntExtra[BatteryManager.EXTRA_SCALE, -1];
 
  result := (100 * level) div scale;
end;

DELPHI

When it comes to Delphi you are stuck with predeclared variables in many circumstances, whether you like it or not. As far as I know, this is one of those circumstances:

uses
  AndroidAPI.JNI.GraphicsContentViewText,
  AndroidAPI.JNI.JavaTypes,
  AndroidAPI.JNI.OS;

function BatteryPercent(const aContext: JContext): Integer;
var
  filter: JIntentFilter;
  battery: JIntent;
  level, scale: Integer;
begin
  filter := TJIntentFilter.Create;
  filter.addAction(TJIntent.JavaClass.ACTION_BATTERY_CHANGED);

  battery := aContext.registerReceiver(NIL, filter);
  level := battery.getIntExtra(StringToJString('level'), -1);
  scale := battery.getIntExtra(StringToJString('scale'), -1);

  result := (100 * level) div scale;
end;

A few things to mention here.

They Seek Him Here, They Seek Him There

First of all Embarcadero seem to have gone out of their way to make it hard to find some of the various bits of the JNI that they have provided.

For example: The Android SDK Intent and IntentFilter classes reside in the android.content namespace. But there is no AndroidAPI.JNI.Content unit.

The intent classes (and interfaces, due to the way the wrappers work) are instead in the “AndroidAPI.JNI.GraphicsContentViewText” unit, a fact that I had to discover using a good old-fashioned “Search > Find in Files” rigmarole.

Initially I wasn’t aware of the “J” prefix on the interface names and “TJ” prefix on classes, so it took an initial, fruitless search for TIntent before I stumbled across that bit of genius.

At first I thought this mouthful of a unit was combination of android.graphics, android.content, android.view and android.text, and perhaps this is how it started out in life since it does seem to contain a lot of stuff from these namespaces.

Then I noticed some members of the android.database.sqlite namespace in there as well.

Whatever noble intentions this unit started out with, it seems now that it is probably just a dumping ground for all sorts of stuff where the Embarcadero devs can stick things when they are in a hurry.

Everything But The Kitchen Sink

The second thing to mention is that there are some pieces missing from the supposedly comprehensive JNI wrappers.

As you can see, the Delphi code uses the AndroidAPI.JNI.OS unit, because the BatteryManager class which – in the Android SDK – provides the constants for the EXTRA_LEVEL and EXTRA_SCALE extras names is located in that namespace.

I needn’t have bothered.

Not only is the BatteryManager class not in the AndroidAPI.JNI.OS unit where you might expect, it is entirely absent, as are the constants it provides. Hence instead you will have to research any such missing constants to discover what the underlying values are and declare them yourself or use them as literals.

Of course, in the case of string literals you first have to put them through the StringToJString() transmogrifier as here.

Pascal That Looks Like Java

The third thing to mention is that Delphi provides none of the syntactic sugar that makes working with the Java SDK more Pascal-like in Oxygene.

To illustrate this, here is the same line of code presented in what I consider to be decreasing order of “Pascal-ness:

  level := battery.IntExtra[ BatteryManager.EXTRA_LEVEL, -1 ];

  level = battery.getIntExtra( BatteryManager.EXTRA_LEVEL, -1 );

  level := battery.getIntExtra( StringToJString('level'), -1 );

For the avoidance of doubt that’s: Oxygene > Java > Delphi

The differences – setting aside inline declarations vs predeclared – are subtle in this case, to be sure, and it’s not about “brevity” – just one character here or there in this case (though taking variable declaration into account, Delphi is far and away the least ‘productive’ language if you measure such things in this way).

It seems that if you want to write Pascal that looks and feels more like Java than Java itself then Delphi is a very good choice these days.

Cumbersome Constructions

As I mentioned earlier, the JNI wrappers use a combination of classes and interfaces. Since interfaces do not have constructors, this makes constructing instances of a class an operation which cannot simply be taken directly from any Java code you might find.

You instead have to use a parameterless constructor and figure out which methods can then be called to achieve the same initialisation that the Java constructor would have provided.

Where the Java class authors have implemented one or more constructors which cannot be approximated in this way, the Embarcadero devs seem to provide init() methods (example: JComponentName) though I can’t be bothered figuring out how you are supposed to work with these.

And this is not applied consistently. If these init() methods are not absolutely needed, then they are not on offer so there isn’t one consistent approach you can take when creating instances of JNI wrapped classes.

Update: With a more complete understanding of the import class mechanism, there is a consistent constructor pattern that can be followed as explained in this separate post.

Something To Investigate …

If you were following my widget example in Oxygene, you will remember that trying to call registerReceiver() in the context of the AppWidgetProvider resulted in an Android runtime exception.

No such problem occurred with the Delphi application.

This leaves me wondering if my theory that the declaration of an intent-filter was responsible for this and thus would also apply to Activity‘s as well is in fact mistaken.

If the restriction applies specifically to AppWidgetProviders this would fit with my further speculation that IntentReceiver (as referenced in the exception message) and BroadcastReceiver (what the Android SDK yields when searching for IntentReceiver) are now – and perhaps always were – synonymous.

An AppWidgetProvider is nothing more or less than a specialised BroadcastReceiver so this would definitely fit.

This bears a little more investigation to pin down, but at least I learned something from this exercise.

26 thoughts on “Getting the Battery Level on Android With Delphi

  1. The JNI wrappers are not exhaustive in the same way that Delphi/Win32’s Win32 API imports are not exhaustive. Documentation on how to write them is similarly absent in both cases. For both Windows and Android you need to do a bit of reading in the source to work out how to access any of the plethora of APIs are available but not pre-imported.

    If you did import the battery manager in the standard way, you’d actually write something like this.

    level := battery.getIntExtra(TJBatteryManager.JavaClass.EXTRA_LEVEL, -1 );

    I’m sure you’ll have comments about that too, but I think it’s appropriate to get the comparisons correct before condemning whatever you choose to condemn.

    Oh, and init is what a Java constructor call causes to execute in the JVM land, so far as I know. When using JNI you’re kind of obliged to call the actual routines that are there in the JVM.

    The similarities with working with the Delphi Win32 are many to be found, inasmuch as the ability is there, but the compiler vendor doesn’t presume to educate the user on all the details. The information is there in the source and keen devs will work it out and make the information available.

    I’m sure, though, if you wanted to, you could spend some time pointing out how difficult and oppressive Delphi 1-XE5 makes talking to any non-imported Windows API call in order to give some symmetry. Generally, however, most people just get on with it. There are always things to learn how to do if you want to go outside the scope of what’s provided in the box.

    1. Importing the BatteryManager in the “standard way”, where that way is undocumented, right ?

      You seem to be painting my complaints as prejudiced, I suggest that your defense of such things is similarly tainted. 😉

      And for the record, I did not conduct this exercise with the specific aim of finding fault. But I am not going to sit here and pretend that the faults that I perceive don’t exist. I’m not an MVP – I can say what I really think. 😉

      Yes, Paul Foster has mentioned that the init() methods are the standard JNI way. So granted, it is the way the underlying JNI works so the inconsistency at that level cannot be laid at the door of Embarcadero perhaps. But the fact that the inconsistency remains in their bridge is absolutely at their feet.

      Whether it was an error of omission or not, the fact that this artefact remains in the JNI bridge is the responsibility of Embarcadero and regardless of where you choose to apportion the responsibility – if that is your priority – this is incidental to the fact that it exists and has to be dealt with, which is what concerns me as a user of that bridge.

      The difference with the WinAPI is that translating ‘C’ headers to Pascal is utterly trivial in comparison to the undocumented process and voodoo incantations involved in importing a Java class through the JNI bridge. Sure, WinAPI imports may also not be documented, but you only need an understanding of ‘C’ and of Pascal and to have the documentation of the ‘C’ API to hand to be effective. This is absolutely not the case with Java and the JNI bridge.

      A better comparison might be COM and Windows Type Libraries, and on that score, extrapolating your argument back through time, you seem to be suggesting that the support for COM in Delphi 2.0 was perfectly adequate.

      1. “Importing the BatteryManager in the “standard way”, where that way is undocumented, right ?” -> Just because the documentation doesn’t cover it does not mean it’s not standard. It’s a long-held mantra that the source is the best (most thorough/accurate) documentation and it’s served up countless gems for Delphi developers over the years. I refer you back to my reference to Windows API routines. That is also not documented, but there are clearly standard ways of doing it. The standard is set by the examples already implemented in the product. Doing it in an different way would be going against the grain.

        “You seem to be painting my complaints as prejudiced, I suggest that your defense of such things is similarly tainted. ;)” -> I am not painting your complaints. I’m commenting on them. My so-called defense is a description of what has been and what still is.

        “I’m not an MVP – I can say what I really think.” I’ve seen you make similar observations before. I don’t know from where this misguided notion stems. I myself have made various rather negative comments about Embo’s marketing statements and choices in the past. Generally, however, my output has always been just a means to convey information to help Delphi and Oxygene developers get things done. My public voice is not about slapping people around the face with my opinion on things, it’s about spreading technical knowledge and information. MVPs are not hired as yes-men lackeys. They are chosen because they are helpful community members who have a history of providing information and help, and the status is a recognition of this. The fact that they are helpful community members typically providing information and services may possibly be linked to them liking the product they work with quite a lot. I certainly like Delphi. I also like Oxygene. I see pluses and minuses with both. Please stop making silly comments that I’m positive you realise are far from a true reflection of the situation.

        “Yes, Paul Foster has mentioned that the init() methods are the standard JNI way. So granted, it is the way the underlying JNI works so the inconsistency at that level cannot be laid at the door of Embarcadero perhaps. But the fact that the inconsistency remains in their bridge is absolutely at their feet.
        Whether it was an error of omission or not, the fact that this artefact remains in the JNI bridge is the responsibility of Embarcadero and regardless of where you choose to apportion the responsibility – if that is your priority – this is incidental to the fact that it exists and has to be dealt with, which is what concerns me as a user of that bridge.” -> My, no one can use you of not being opiniated, Jolyon. It has to be dealt with, does it? Ok, you’re the boss and it’s clearly a major trouble spot. Personally, it hadn’t really posed me any issues. I’m not sure I’d appreciate Embo spending much time on dealing with this minor consistency situation, when there are are many more compelling problems to focus on resolving.

        “The difference with the WinAPI is that translating ‘C’ headers to Pascal is utterly trivial in comparison to the undocumented process and voodoo incantations involved in importing a Java class through the JNI bridge.” -> Describing one example as trivial and one in colourful terms you’ve chosen to show you had some problems doesn’t actually make one trivial and one overly complicated. I used the source to learn how to fumble my way through importing API routines, with all the fun to do with data structures, alignment, calling conventions and so forth. Trivial is certainly not a term I’d expect anyone to use, even if familiar with C and the ‘utterly’ addition surprises me even more. It requires learning, and the learning comes from looking at the examples. You may have forgotten the learning process as it was so long ago; who knows? I went through the same learning-by-source approach with the Android stuff, and to me it seems barely any more difficult. I can only imagine we experience things differently, as I didn’t encounter any requirements for voodoo, but maybe it just came easier to me this time round.
        That’s not to say that the bridge mechanism isn’t left wanting. The annoyance of no shipped support (as yet) for accessing additional .jar files was extremely disappointing. It’s doable, but currently only with much effort and long-winded, prolix code

        “Sure, WinAPI imports may also not be documented, but you only need an understanding of ‘C’ and of Pascal and to have the documentation of the ‘C’ API to hand to be effective. This is absolutely not the case with Java and the JNI bridge.” -> When first encountering them, I required existing import declarations to make sure I got the layout, and external declaration aspects correct, and any cases where trivial primitive types were required I was definitely poring over the RTL examples. You appear to be trivialising what I often found very much other than trivial translation. Maybe this is simply a reflection of how well-versed at C and Delphi you are when compared with me.

        “A better comparison might be COM and Windows Type Libraries, and on that score, extrapolating your argument back through time, you seem to be suggesting that the support for COM in Delphi 2.0 was perfectly adequate.” -> Because you feel there might be a better comparison elsewhere doesn’t actually change what I was suggesting just because you say so. No, I’m still suggesting the bridge has a good comparison with importing Windows API routines. And if you found importing Windows routines trivial, then good for you – your expertise in that area shines through. However I clearly find the Android importing rather easier, so it all seems to be quite relative.

        1. Just because the documentation doesn’t cover it does not mean it’s not standard

          No, but I can’t actually see where I said or even implied that it did. So I’m not entirely clear on what your point is exactly.

          I don’t know from where this misguided notion stems

          I think you should check your MVP agreement.

          It has to be dealt with, does it?

          Um, yes. Not in the sense that every Delphi developer targeting Android is forced to deal with it, but that a developer wishing or needing to work with the JNI will of course have to work with what they find in the bridge, and this is what they will find there.

          This isn’t an opinion – “ated” or otherwise. Just an observation.

          You appear to be trivialising what I often found very much other than trivial translation. Maybe this is simply a reflection of how well-versed at C and Delphi you are when compared with me.

          Quite possibly. But then that is precisely the difference that I myself highlighted. A familiarity with ‘C’ and Pascal does perhaps make converting between the two quite trivial even if it is not so trivial for someone who does not have that familiarity with both languages. But you don’t need an understanding of any intermediate technology to “bridge” the two.

          But in the case of the JNI bridge, even deep knowledge of Java won’t help much since building the bridge doesn’t involve simply mapping well understood Java declarations onto equally or better understood equivalent Pascal. It requires an understanding of the mechanics, implementation and any limitations of the bridging technology itself.

          This may be something that a consultant may enjoy doing in the process of – say – compiling material for a presentation at a conference, but this is not the majority of Delphi developers (though sadly I sometimes think it soon may be).

          1. “I think you should check your MVP agreement.”

            You’re linking to my post to support your accusations of bias on the part of MVPs?!
            http://members.adug.org.au/2012/08/29/xe3-pro-eula-changes-and-mvps/

            The same post in which I as an MVP publicly called Embarcadero out on their plan to change XE3 Pro licensing and described the lengths I went to obtain an assurance that being an MVP didn’t mean having to blindly follow the company line.

            You may not have read this paragraph in another recent post of mine,

            “Either way if you purchased XE4 to do iOS development and you don’t have a maintenance contract or a free upgrade to XE5 you have a good reason to feel shortchanged and I’d encourage you to let Embarcadero know it.”
            http://members.adug.org.au/2013/09/18/dont-be-a-bloody-idiot

            There’s never been any suggestion made to me by Embarcadero that those remarks violate my MVP agreement.

            Additionally if you read my comment on this same issue to Jason Sweby’s recent pricing blog post.
            http://delphidisciple.blogspot.com.au/2013/09/the-rising-cost-of-being-delphi.html
            and click on the +2 you’ll see that Jim McKeeth, who now runs the MVP program is one of the two who endorsed my comment.

            1. No. I am linking to your post as evidence of the fact that MVPs are required to enter into a legal agreement that prohibits them from being critical. There may be non-binding assurances about how that agreement will be enforced which would explain the occasional exception but does not alter the fact of the legal agreement itself. Unless it has changed. But if it had, I am sure you would have mentioned that by now.

              As for the head of the MVP program +1’ing a comment defending the MVP program, I’m not sure what you think this establishes. I wouldn’t expect anything else. Would you ?

              If he had +1’d your “Bloody Idiot” post on the other hand, then you might have had a point, but I don’t think he did, did he ? Did any other MVP ?

              1. Brian’s criticism of Error Insight isn’t harsh enough.

                Jim’s +1 on a comment that quotes and directly links to my “bloody idiot” post isn’t endorsement enough.

                The assurances I sought and received about the actual intent behind that clause are worthless.

                I’m sorry all these people didn’t have the foresight to sufficiently tick enough boxes to satisfy your personal standard of truth.

                Here’s something you can choose either to believe or not to believe. I’d like to say I don’t care either way but in fact I do.

                If I am ever made aware of that clause being used in any way other than the way it was described to me I will resign as an MVP and attempt to convince as many other MVPs as I can to do the same.

              2. Yes, I’m afraid those assurances you obtained are worthless, legally. Unless they resulted in a change to the agreement you signed. But you haven’t said that they did.

                Neither of us can really say what Jim was endorsing. All I can say is that as I see it if he wanted to support your post he could have done so directly, but he didn’t.

                Brian’s criticism of Error Insight was no different to the multitude of voices already having said exactly the same thing. Probably nobody much cares about how crap Error Insight is these days since people long since gave up trying to put up with it. Least of all Embarcadero. I have even seen it said that Embarcadero know full well just how dire it is and that it needs a complete re-write but aren’t prepared to put the time and effort in that it needs.

                I don’t want to get into a shopping list of he said this and he said that which is why I resisted adding any further commentary other than to respond to the specific point you raised, but since you did raise Brian’s record, I am not just dismissing this one instance that you raise. There are other things I am taking into account. Not least in the context of your post that I linked to and the EULA debacle, the only mention of this that Brian makes – on his blog at least, I’ve not found any other mention he may have made elsewhere – is to acknowledge that it happened. He offers no opinion of his own let alone criticism. On a subject for which Embarcadero were roundly and vocally criticised from all quarters (well, most) and rightly so even by at least one MVP – your good self – who explicitly invited other MVP’s to lend their voice.

                By the time that Brian even mentions it, the debacle had been resolved and Embarcadero had been forced to back down (except they really hadn’t because they have now achieved the same result with the acquisition and positioning of AnyFireDAC). But up to that point he doesn’t even mention it.

                Coincidentally, this post where he barely acknowledges one of the hottest talking points at the time only after the fact, he also mentions that he is now an MVP.

                Of course, it’s notoriously difficult, if not impossible, to prove a negative. So I have a hopeless job of trying to establish that Brian – or anyone else for that matter, let’s not make this personal though I fear it is too late and not at all what I at least intended – has not said something when they could have.

                But should such convincing evidence come to light I have no problem believing that you would respond as you say you would.

                I do not doubt for a moment that MVP’s are fine, honourable people. But to suggest that they are not bound by a legal agreement voluntarily entered into defies the legal reality (though some may feel more bound than others). 🙂

                I ascribe no negative connotations to that and don’t quite understand why you are so defensive about it. It is what it is. That’s all.

                Much as I would love to continue this debate (though I feel it would be best continued over a beer, not TCP/IP), I have to get ready to go to a jam session tonight. A little band that get’s together about once every 2 years at the current rate! I fear we may all prove to be a little rusty. 🙂

          2. “This may be something that a consultant may enjoy doing in the process of – say – compiling material for a presentation at a conference” -> In my case I decided to do the talk because I’d gone through a number of interesting technical areas while doing some work for a client. I felt it good general information to share. I like to share possibly good information when I have time, on whatever products I’m working with. I try to make a habit of it. I don’t make a regular habit of sharing opinions, unless the issue directly affects me, such as the case with Error Insight.
            So anyway, your apparent assumption about how I got the knowledge of the product I’m talking about was off the mark again.

            1. You’re making assumptions about assumptions.

              I said only that a consultant might enjoy doing it in the course of that exercise. The distinction being that having to do it when you’re up against a deadline and supposed to be working on functional aspects of your project rather than wrestling with esoteric aspects of your compiler technology is not going to be enjoyable. Or at least, not as enjoyable.

              It also has to be said that a consultant being paid by the hour is also going to welcome the opportunity to rack up some good billing time on such an exercise. 🙂

              Just to save you the effort of getting all righteously indignant about that, this is not to assume that your work for that client was billable by the hour on this particular occasion. For all I know it was a fixed price contract and you had to wear the overhead. But for someone who is billing by the hour, every hour is billable. 🙂

      2. “I’m not an MVP – I can say what I really think.”

        I’m really starting to find these sort of comments quite offensive as I’m sure my other fellow MVPs are as well.

        Have you noticed a change in Brian’s blogging since he became an MVP? I haven’t. In fact off the top of my head I can remember a reasonably recent comment he made about the embarrassing inadequacies of Delphi’s Error Insight.

        1. Unless things have changed, it is a simple fact that Embarcadero MVP’s have entered into an agreement by which they are legally bound to not be critical. I don’t see why you should find it offensive to be reminded of that.

          As for Brians stinging criticism of Error Insight, I am sure one more slap over the wrist with a wet bus ticket about an aspect of their product that even their most ardent fans complain about won’t cause any concern on the Embarcadero MVP panel. I don’t think he need be too concerned about his MVP renewal. 🙂

  2. Interesting comparison.

    In a real-world situation it would probably be wise to wrap this in a generic component that has the same interface on all platforms, or at least to abstract this specific implementation away.

    When all of your code looks like this you’re basically just coding java with pascal syntax. I don’t see the advantage of that over “real” java because you miss out on all the cool toys that java android devs have at their disposal.

    1. Yes. It is an oft heard complaint that Oxygene has no cross-platform library but if FireMonkey didn’t exist then neither would Delphi. There is no cross-platform library with Oxygene but there is absolutely nothing to stop one from being put together.

      It is interesting to note that FireMonkey also does not appear to offer any cross-platform solution to reading the battery level “out of the box” either. A curious omission for a mobile platform where responding appropriately to battery condition can be a crucial consideration.

      As for the benefits of using Pascal to write Java, the benefits flow the other way. You are missing nothing of what Java offers – at least not that I have yet run into. Did you have some specific examples in mind ? I would genuinely be interested.

      In my experience so far, using Oxygene brings additional language features that Java lacks, without breaking the fact that you are fundamentally producing Java code. 😉

    2. Yes, I find it quite interesting as an example of “Stockholm Syndrome” how some users are so quick to defend their captors. Just yesterday I watched a video of a talk from a Python conference about the state of Python on Android (in a word: poor). The best current solution for non-game software involved the use of Pyjenius, which provides a bridge between Python and JNI. The speaker did demonstrate how this can lead to some Java-like code and wasn’t very “Pythonic”, and ended with a laundry list of areas that could be improved (including abstracting the JNI away into a more Pythonic framework like you suggest with Delphi and a component). A member of the audience posed a question thusly: if he wanted to develop with Python on Android and needed to use Pyjenius, he’d need to learn a lot about the Android/Java APIs and since all of the literature will be in Java, he’d need to familiarize himself with this as well. This could take a few months, at the end of which he’d have a decent understanding of the Android/Java framework and Java itself. After all that, why not just develop in Java? The speaker agreed with him that that was a very realistic scenario and exactly why Python wasn’t a first class citizen on Android and why Pyjenius needed to be improved.

      Now I come here to read a Delphi user (Mr. Long) defending both JNI calls and needing to make Win32 calls. Outside of Delphi Island, neither of those are acceptable and effort would be expended to abstract both of those things away. Exhibit one: you can’t even launch a PDF with the same code on Delphi, mobile or desktop; per Stephen Ball’s blog, you need to use IFDEFs and the system call for each OS. 18 years, and VCL never gained a method to launch an application. Meanwhile, Qt, Python, FreePascal and most other cross-platform tools I can think of all have a routine to do so.

      >I’m sure, though, if you wanted to, you could spend some time pointing
      >out how difficult and oppressive Delphi 1-XE5 makes talking to any
      >non-imported Windows API call in order to give some symmetry.

      Yes, compared to many other cross-platform frameworks.

      >Generally, however, most people just get on with it.

      Most Delphi people. No one else would pay that kind of money and settle.

      >There are always things to learn how to do if you want to go outside the
      >scope of what’s provided in the box.

      For what they charge, we need a better box. 😉

    3. “When all of your code looks like this you’re basically just coding java with pascal syntax.”

      what is a programming language, if not syntax? The Java Language, Object Pascal, C#, C++ all are object oriented programming languages. What distinguishes each language is the syntax (and the language’s capabilities —which for Oxygene are unprecedented).

      Shocker then, that a Pascal compiler for the Java platform is “just” a compiler for that platform, but with a Pascal syntax? What else *should* it be?

  3. Well… Oxygene-Java interop is implemented entirely at the compiler level, Delphi-Java interop entirely at the library one. Given Oxygene for Java directly targets the JVM, I’d hope it *was* seemless, in the same way I would hope using Delphi to call a C API would be.

    Even still, could the Delphi/Java bridge be better? Probably, but there are more important fish for Embarcadero to fry first. IMO of course…

    1. It isn’t accurate to describe Oxygene-Java as “interop”. As you say, the Oxygene compiler is a Java compiler, it simply happens to accept Pascal on the front-end. If that is “interop” then Delphi is Pascal-x86 “interop”. 🙂

      I’m also curious to know how a bridge could be better.

      You seem to have some idea as to how, and I would be interested to know what you have in mind ?

      Currently, far from being “better”, it is worse than using Java itself, as evidenced by the constructor inconsistency which – as has been pointed out by others – is an artefact of the underlying Java which curiously neither Oxygene nor the Java language itself, with their non-interop support for the environment do not suffer from, but the potentially “better” bridge does.

      The indication would seem to be that even if the bridge could be better (how?) there appears to be no appetite for making it so at Embarcadero. And why would they ? As far as they are concerned you should be doing everything in one, cross-compilable code-base.

      Facilitating platform specific coding, beyond paying lip-service, would be an admission of the failure of that approach.

      1. ‘It isn’t accurate to describe Oxygene-Java as “interop”’

        I also said it targets the JVM, and as such, *should* have seemless interaction (if you would prefer that word) with the Java APIs. Insofar as it doesn’t, then the question may be asked: ‘what’s the point?’, similar to how one might post the same question if Delphi was not able to directly access a C API. Or in other words: if Oxygene really does provide a seemless way to interact with the Java-based API (and by the sounds of it it does), then great, but not /that/ great given one would expect it to.

        By the by, this is something that put has put me off Xamarin for Android (along from the high price!) – using it means working with a managed code language, but not the /native/ managed code language. As such, you don’t have ‘native’ access to anything, and however quickly Xamarin update their bridging code they cannot hide the fact. (If I had an emotional attachment to C# things might be different… but I don’t.)

        ‘I’m also curious to know how a bridge could be better.’

        You misunderstand me – I’m saying, calling a managed code API should be second nature to a managed code compiler, just like calling a native code API should be second nature to a native code compiler.

        ‘The indication would seem to be that even if the bridge could be better (how?) there appears to be no appetite for making it so at Embarcadero.’

        Prioritising this would be insane given the current state of FMX – the current bridge is ‘good enough’, and I’m doubtful it could become substantively better without dropping the native code approach entirely, which would involve its own hassles: the current approach means much of the wider RTL is more easily ported to Android given the latter’s Linux base.

        1. “I also said it targets the JVM”

          Yes, you did. And that part is entirely accurate. But this doesn’t make the preceding use of the term “interop” any less inaccurate (or at least misleading). 🙂

          You seem to be under the impression that the integration/interaction is not seamless for some reason (“in so far as it doesn’t”) and I don’t understand where you get this impression. I am reluctant to assure you that there is “seamless interaction” as this expression usually implies that there is a “joining” but which has been successfully covered up. But in the literal sense of it, yet, there is no gap, no bridge, no join between Oxygene and Java. Oxygene participates directly in the Java world.

          Not just Android, any Java (It’s not Oxygene for Android – but Oxygene for Java).

          Perhaps this will help clear it up: When you add “android.os” to the uses list in an Oxygene unit you are not bringing some Oxygene unit containing exposures or wrappers of Java classes into scope. There is no android.os.pas.

          You are directly referencing a Java Namespace within a Java Package (JAR) (which is in turn simply listed as a “reference” by the project).

          I can only say again that when you write Oxygene for Java you are writing Java; you are simply enjoying the benefits of being able to do so in a Pascal dialect. 🙂

          As for this rather odd claim of a “wider RTL”…. Since the NDK does not support the same breadth of capabilities on the platform as the SDK, and given that the creators of the platform have a very narrow idea of what is an appropriate use of the NDK (games, or game-like apps) to call it “wider RTL” needs to be backed up with some explanation of why you (or whoever told you this) thinks it so.

          I think there are some really rather desperate attempts to find something to appreciate in the NDK based approach taken by FireMonkey, and in doing so there is only a tenuous grasp retained on the real world in some quarters.

          The only benefit in FireMonkey is the write-once compile for everywhere a range of supported devices. To try to suggest that it also facilitates a better platform-native solution than an actual platform-native solution is just ludicrous. The fact that some people feel the need even to try suggests that the one-codebase fantasy is perhaps starting to unravel.

          1. Dearie me – I used the word ‘interop’ in the context of a comparision between Delphi and Oxygene. When making comparisions, you need to use the same words and concepts in relation to each of the things being compared… otherwise there won’t be a comparision.

            You seem to be under the impression that the integration/interaction is not seamless for some reason

            I am neither asserting nor denying such a thing, but will accept the claim for the sake of argument. I leave aside the factual truth of it partly because I haven’t used Oxygene myself, and partly because I can still remember what you wrote about FMX when it first came out – I haven’t been able to take your opinionated descriptions at face value ever since! 😉

            As for this rather odd claim of a “wider RTL”…. Since the NDK does not support the same breadth of capabilities on the platform as the SDK

            Er, I wasn’t referring to the NDK as a ‘wider RTL’ for Delphi – I was referring to the Delphi ‘wider RTL’, oddly enough. As I use the terms, the Delphi RTL in a ‘narrow’ sense is just the System unit, the RTL in a ‘wider’ one everything under the System unit scope. For example, for OS X and iOS, Delphi’s threading support uses the pthreads API; target Android, and phreads is used internally once more, with much of the implementation single sourced for all *nix platforms.

            I think there are some really rather desperate attempts to find something to appreciate in the NDK based approach taken by FireMonkey

            Is that supposed to be directed at me? If so, there isn’t really much of a necessary connection between using the NDK and FireMonkey. Care to explain? (Given you’re such a stickler for words, I’m sure by ‘FireMonkey’ you mean the visual component framework, not Delphi for Android at large…)

            in doing so there is only a tenuous grasp retained on the real world in some quarters

            In the real world, people are discovering Android Studio and realising it isn’t bad…

            1. Typo – “Given you’re such a stickler for words, I’m sure you’re by ‘FireMonkey’ you…” should read “Given you’re such a stickler for words, I’m sure by ‘FireMonkey’ you…”

              1. No worries. I’m not immune from such typos myself. I read through my posts at least 2-3 times before posting and yet still small mistakes slip through. Just goes to show that you should never rely on editing your own work. 🙂

                (I fixed your typo for you)

            2. When making comparisons you need to be comparing apples and apples. You can’t just call an orange an apple in order to make an apples and oranges comparison appear more appropriate than it is.

              I explained why I thought you were under the impression that the interaction isn’t seamless. It came from things you had said.

              Recently I went back and read my own initial posts on FireMonkey myself. All I can say is that at that time (FireMonkey hadn’t actually been released yet – it was the launch preview) the promise was certainly, um, promising. My first impressions of FireMonkey were just that first impressions. Not an ‘opinion’. But then it’s not so effective to dismiss someone as First Impression-ated I guess (not you, someone else).

              And of course, at that point we didn’t actually know how the Android support was going to be delivere or – as it turned out – what the iOS support was actually going to look like. All we had was the beta bait. Nobody knew about the switch that was yet to come. 🙁

              I apologise for the confusion re the “wider RTL”. Since modern platforms all provide rich RTL’s I tend to forget that Delphi still relies on it’s own. 😉

              The “desperate attempts” comment was not directed specifically nor solely at you, no.

              As for explaining why I connect NDK and FireMonkey, the two simply are connected though the relationship is not commutative.

              That is, you can write an NDK app without using FireMonkey (though you will have to go around the houses to do so using Delphi if it even possible at all – I suspect that there will be at least some bit of FireMonkey involved in getting an NDK app launched) but you cannot write a FireMonkey app without using the NDK.

              But when I say “FireMonkey” I mean the cross-platform framework that Embarcadero themselves now refer to as a “platform”, not just the visual component aspects of that framework. There are whole areas of the FireMonkey framework which are not at all visual in nature.

        2. “then great, but not /that/ great given one would expect it to.”

          grading on a curve, are we?

Comments are closed.