"Why Apache Harmony" or "How to use Java 8 on Android" - java

Most of us have heard by now of the cool features Java 8 will bring, but Android will not support it. This is because of Google using Apache Harmony for Android. This is what is keeping us (the android app developers) from improving our code with lambdas, default implementations in interfaces, switching on a String and a lot more. Surely, we will handle for some time, but what if some libraries we use in our apps start to use Java 8 features? As far as I know, this will not work (please correct me if wrong). This creates incompatibility between Standard-Java and Android-Java. It cannot be what Google intends, or at least I can't think of a reason why a company, developing a widely adopted operating system, would wan't to permanently stay with an old Java version.
Questions:
Why do they use Apache Harmony?
Why can't they adopt a newer version of java?
If they don't want Oracle's Java, why can't they use a subset of OpenJDK (licensing noob here)?
Do you know of any plans to update the used Java version?
Do you know of any way to use Java 8 classes on current Android systems?

Why do they use Apache Harmony?
Because Sun refused to provide Google with a license for Sun (now Oracle) Java under terms that were acceptable. Google and Sun negotiated, but they ended up walking away from the deal.
Nitpick: in fact, the Android libraries are not Apache Harmony. They started out as based on Harmony, but the two codebases have diverged. Furthermore, the Apache Harmony project was officially "retired" in November 2011.
Why can't they adopt a newer version of java?
Firstly, Android does not run Java(tm). It runs a language that is identical to Java with a class library that is functionally equivalent to a subset of the Java class library (+ Android-specific libraries), on a virtual machine with a different instruction set.
From a technical pespective, they could ... but only if they put in a lot of work into implementing Java 7 and Java 8 language features, library features, etc, for the Android platform.
UPDATE - As of Android 19 (KitKat) and Eclipse ADT 22.6, Android does now support the Java 7 language extensions; see http://tools.android.com/recent/eclipseadt226preview
If they don't want Oracle's Java, why can't they use a subset of OpenJDK?
I don't think that switching to OpenJDK would change anything. Oracle Java and OpenJDK are 99.9% the same.
Anyway, there may be licensing and related legal issues. (And to get a feel for that, read up on the Oracle vs Google lawsuit ... that is going to appeal.)
More likely, Google doesn't see enough commercial value to counteract the (massive) effort it would take to change, and the disruption it would cause to the Android ecosystem ... which already suffers from problems with fragmentation.
Do you know of any plans to update the used Java version?
No I don't. It doesn't mean that there aren't plans, but if there are, they are not public.
Do you know of any way to use Java 8 classes on current Android systems?
You could port them. Or at least, you could try to port them. (Some Java APIs have an intimate relationship with the native code side of the JVM ... and that could make porting problematic.)

Do you know of any way to use Java 8 classes on current Android systems?
There are a few libraries which backport parts of Java 8 API (see the update section below for native support of these APIs in the latest Android versions):
ThreeTenABP backport of Java 8 date and time API optimised for Android
Stream support is a backport of the Java 8 java.util.function (functional interfaces) and java.util.stream (streams) API for users of Java 6 or 7 supplemented with selected additions from java.util.concurrent which didn't exist back in Java 6.
And you can use retrolambda (along with gradle-retrolambda plugin) to utilize lambdas in Android development.
UPDATE
Android Studio 3.0 started to provide built-in support for some of Java 8 language features, which are:
Lambda expressions
Method references
Type Annotations (information is available at compile time, but not at runtime)
Repeating annotations
Default and static interface methods
Also starting from API level 24 the following Java 8 API are available:
java.util.stream
java.util.function
java.lang.FunctionalInterface
java.lang.annotation.Repeatable
java.lang.reflect.AnnotatedElement.getAnnotationsByType(Class)
java.lang.reflect.Method.isDefault()
API level 26 (Android O) added java.time API support.
UPDATE 2020/01/17
Android Studio 4.0 includes support for using a number of Java 8 language APIs, by using technique called desugaring, without requiring a minimum API level for your app:
https://developer.android.com/studio/preview/features#j8-desugar
The following set of APIs is supported in this release:
Sequential streams (java.util.stream)
A subset of java.time
java.util.function
Recent additions to java.util.{Map,Collection,Comparator}
Optionals (java.util.Optional, java.util.OptionalInt and java.util.OptionalDouble) and some other new classes useful with the
above APIs
Some additions to java.util.concurrent.atomic (new methods on AtomicInteger, AtomicLong and AtomicReference)
ConcurrentHashMap (with bug fixes for Android 5.0)
To support these language APIs, D8 compiles a separate library DEX
file that contains an implementation of the missing APIs and includes
it in your app. The desugaring process rewrites your app’s code to
instead use this library at runtime.
To enable support for these language APIs, include the following in
your module’s build.gradle file:
android {
defaultConfig {
// Required when setting minSdkVersion to 20 or lower
multiDexEnabled true
}
compileOptions {
// Flag to enable support for the new language APIs
coreLibraryDesugaringEnabled true
// Sets Java compatibility to Java 8
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.4'
}
More technical details on how desugaring is implemented, can be found in Jake Wharton's articles:
Android's Java 8 Support
Android's Java 9, 10, 11, and 12 Support
D8 Library Desugaring

Update.
Android is planning to use the OpenJDK. Possibly because they are thinking like you and wants to use the Java 8 features. See this

Related

Relationship between OS version, API Level, and Java version

I know there are a lot of questions on here about Android API Level and Version but this question is different so please don't mark it as a duplicate.
I am wondering how Java version 1.6, 1.7, 1.8... relates to those two. The source of my confusion is me trying to use the Pattern.compile method with the Pattern.UNICODE_CHARACTER_CLASS flag as seen below.
Pattern pattern = Pattern.compile("\\b" + keywordToCheck + "\\b", Pattern.UNICODE_CHARACTER_CLASS);
From the docs on Pattern.UNICODE_CHARACTER_CLASS it says that it says Since: 1.7, which I assume to mean it is available in Java version 1.7 and above. I am trying to use that line of code in an Android project but every time I run it on my device I get:
java.lang.IllegalArgumentException: Unsupported flags: 256
Below are the relevant parts of my build.gradle file
defaultConfig {
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
From my understanding this means my app will use any API level 19 and above, which means it can run on Android 4.4 (KitKat) or higher. The device I'm running the app on has Android 6.0. How does the Java version fit into this? I am using Android Studio 3.0 which says I'm using:
Android Studio 3.0
Build #AI-171.4408382, built on October 20, 2017
JRE: 1.8.0_152-release-915-b08 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Mac OS X 10.12.6
Can someone explain to me why I'm getting this error, and also the relationship between Android API Level, Version, and Java version? Thank you
In the case of your given example, that flag wasn't added until API 24. In a lot of cases, even though support for a given language level (e.g. 7) was added earlier doesn't mean everything is added instantly. Some things are waited with for whatever reason Google has for waiting with it.
I can't tell you why because I don't know.
And as Gabe mentioned, the versions of Java isn't necessarily compatible with Android.
So because of your code where you use the flag on API 19 and up, you'll get a crash on versions between and equal to 19 and 23 because the flag isn't added yet.
And it's also worth noting that version compatibility doesn't limit versions of Java by versions of Android. Now you can for an instance run Java 8 on whatever version of Android you want. This is compatibility.
However. If you read Android Java 8 Language Features, it says (emphasis mine):
Android Studio 3.0 and later supports all Java 7 language features and a subset of Java 8 language features that vary by platform version.
I'm using Java 8 as the example here, but this applies to mostly every version of Android and java.
Essentially:
The flag you're using wasn't added until API 24. AFAIK, usage wasn't added even though the hard-coded variable is there
Android doesn't necessarily have every single Java API, and these vary by versions of Android
Versions of Java isn't limited by API, but the accessible features vary. Meaning you can run Java 8 on API (random number) 12 if you wanted to.
There's no fixed relationship (Android [x] = Java[x]) between the two. Different fields/methods/classes may be added eventually, instantly (on release of support for a given version of java) or not at all.
The regular Java and the version of Java used in Android are two very different ones, because Android is platform-based while Java is version-based. You can't compare versions between them, and they both have separate documentations.
It's worth noting that for Android (Java) questions you should look at the Android docs which can be found in the API reference instead of using the Oracle documentation which doesn't apply to Android because of the massive differences in the API.
When it says available since 1.7, notice who's docs you're looking at- the Oracle (official Java docs). So it will always be Java version. Android documentation will always give you the Android SDK version its available since.
Note that Android is not always 100% compatible with Java's official versions. It tries to be, but obviously large chunks of the library just aren't there. When in doubt look at the Android documentation of the class, not the Oracle.
As for Java versions- they're independent from Android versions, mostly. Java 8 was just made officially fully supported with AS3. Before that it was deemed experimental. You can still use Java 7 if you want. For Java 8, most language features are available on all platforms, but one or two require a minimum SDK version of 24. The two I know of like that are Java streams and Annotation types/repeated annotations.
For your specific problem, note the android documentation says this about the flag: "This flag has no effect on Android, unicode character classes are always used." So you can just remove it.

Could I use apps developed with android N platform on previous versions of android OS

Seems google introduce quite a lot of interesting features in android N platform, for example Java 8 partial support. I want to use it for my first android application. However I have a question - if my app will be implemented using Android N tools using Java 8 features, but with settings minimal sdk = 4.1 will my application work on Android 4, 5, 6?
Yes, your app will work on previous versions of Android if you use the Support Libraries. These are updated with new versions of Android to provide backwards compatibility to new features. This is a common practice.
https://developer.android.com/topic/libraries/support-library/index.html
For Java 8, it sounds like you will need to be selective in what you use.
From the documentation: https://developer.android.com/preview/j8-jack.html
Supported Java 8 Language Features and APIs
Android does not currently support all Java 8 language features. However, the following features are now available when developing apps targeting the Android N Preview:
Default and static interface methods
Lambda expressions (also available on API level 23 and lower)
Repeatable annotations
Method References (also available on API level 23 and lower)
Note: To test lambda expressions and method references on earlier versions of Android, go to your build.gradle file, and set compileSdkVersion and targetSdkVersion to 23 or lower. You will still need to enable the Jack toolchain to use these Java 8 features.

Android and Lambda

I need to integrate some code with extensive usage of Java lambda functions.
Several restrictions I have demand that I develop my project using Eclipse Mars, with the latest ADT plugin, and not Android Studio.
The problem is that using Lambda functions demands using 1.8 JDK compliance, but if set so, I get this message:
Android requires compiler compliance level 5.0 or 6.0. Found '1.8' instead.
How can the two live together in harmony?
Edit:
This is not a a duplicate of the questions suggested, as I'm asking about ADT Eclipse, and since the last update in that question, Android does support Java 8, so no only is this not a duplicate, but that question is now (after 1.5 yrs after the last update) obsolete.
Update on Java 8 language features on Android
Lambda is back ported to older versions of Android.
This is a feature from Android Gradle Plugin 3.0 and above, lambda is back ported to older Android OS versions as part of other Java 8 language features.
Add this to your Gradle build scripts to enable the feature.
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
For more details, see Use Java 8 language features, and Android' Java 8 support.
As #dhke said, there's no support for Java 8 on Android yet.
Use Java 8, Build For Java 6/7
But you can still use JDK 8 to develop Android application. You just need to set source compatibility to either 6 or 7 depends on your minSDKVersion. Thus, you would lose any new features introduced in Java 8, like lambda in your case.
Backport of Lamda
Since you have extensive usage of lambda, Retrolambda might be an option for you. It provides backport of lambda for pre-Java 8 versions. It has Maven/Gradle/command line plugin to enable the support.
Other Backports
If you need other Java 8 features, AFAIK, ThreeTen ABP provides backport support for Java 8 Date Time API.
You cannot currently (as up to at least Android 5.1.1) use lambda functions on Android.
Lambda functions require new Dalvik (not necessarily JVM!) opcodes (liberate-variable, box-lambda, unbox-lambda, capture-variable, create-lambda, invoke-lambda) that neither Dalvik nor ART currently have support for.
It looks like google might have scheduled (though nothing seems to be official yet) Java 8 support for post 5.1.1 (API Level 23 and later). At least the smali disassembler already added support with a distinct reference to the API level:
https://github.com/JesusFreke/smali/commit/144951a9e9e6c87866245f2bdeebf0ebedaa0e38:
Add new -X/--experimental flag to [dis]assemble opcodes not in art yet
Add new opcodes liberate-variable, box-lambda, unbox-lambda, capture-variable, create-lambda, invoke-lambda
Add support for encoding 25x instructions
Adds LambdaTest to check new opcodes assemble/disassemble properly
And also
https://github.com/JesusFreke/smali/commit/144951a9e9e6c87866245f2bdeebf0ebedaa0e38#diff-5d7892344c0b747d3667bf8623c690c5R66
options.apiLevel = 23; // since we need at least level 23 for lambda opcodes
This only marks the opcodes, not the necessary library changes. It also does not tell us anything about Android itself, so I'd suggest not to take this as an official release schedule.
Android does support Java 8, so no only is this not a duplicate
As of Android N preview release Android support limited features of Java 8 see Java 8 Language Features
To start using these features, you need to download and set up Android
Studio 2.1 and the Android N Preview SDK, which includes the
required Jack toolchain and updated Android Plugin for Gradle. If you
haven't yet installed the Android N Preview SDK, see Set Up to Develop
for Android N.
Supported Java 8 Language Features and APIs
Android does not currently support all Java 8 language features.
However, the following features are now available when developing apps
targeting the Android N Preview:
Default and static interface methods
Lambda expressions
Repeatable annotations
There are some additional Java 8 features which Android support, you can see complete detail from Java 8 Language Features
I don't think this is going to work.
In order to use lambdas, you need source compatibility level 1.8. In order for the DEX compiler to work you need target compatibility 1.7. Eclipse is not going to let you set the target compatibility below the source compatibility (picture below).
Note that this is unrelated to IntelliJ's habit of thinking it knows way better than you do, what your code should look like. It can show you a lambda, even when the actual code is an anonymous class.
UPDATE: Since a few days, Android Studio 3.0 is out on stable. It officially supports a subset of Java 8 features, lambda expressions among them.
According to this Android Developers Blogpost from March 14th, 2017, google
decided to add support for Java 8 language features directly into the current javac and dx set of tools, and deprecate the Jack toolchain. With this new direction, existing tools and plugins dependent on the Java class file format should continue to work. Moving forward, Java 8 language features will be natively supported by the Android build system. We're aiming to launch this as part of Android Studio in the coming weeks, and we wanted to share this decision early with you.
So we probably won't have to wait much longer for Java 8 in Android Studio.
Reverse The Lambda Syntax
As far as I know, everything done in the new Java 8 Lambda syntax can be done using old-school Java code such as anonymous inner class. (Oracel Tutorial) (Oracle Quick Start)
To ease the burden of undoing the Lambda syntax, some IDEs such as NetBeans can suggest automatic revision of code in either direction to/from Lambda syntax. With one-click of approval, the syntax is auto-magically swapped. See the NetBeans document on Using Lambda Expressions Support.
Here is a screenshot of NetBeans offering to turn a Vaadin button’s Button.ClickListener from Lambda syntax to an anonymous inner class. Notice the mouse pointer clicking on the light bulb icon on line # 107.
To enable this feature in your IDE, you will need to enable Java 8 in your project temporarily. After undoing all the Lambda syntax, switch your project back to Java 6/7. In NetBeans the way to enable Java 8 is in your project > Properties > Sources > Source/Binary Format (popup menu) > 1.8.

Using Java 1.8 for Android project [duplicate]

This question already has answers here:
Is it possible to use Java 8 for Android development?
(28 answers)
Closed 7 years ago.
Is there any issues with using Java 1.8 for an android project targetting API 14 and above? I can't find any documentation on this and would like to use Optionals.
Edit: Mainly focused on optionals (not duplicate).
for Optionals only you can also use guava - if you want other features you might want to have a look at retro-lambda
Also think twice about Optional - try to do it at compile-time as much as possible with Annotations like #Nullable #NonNull - same effect - more speed
As far as I know you can't do this. Android works with a subset of the Java APIs and with the Java language as-of Java 1.5 (from memory). So Optional won't be available in the APIs included in Android and 1.8 language features (lambdas, etc) are not available to you when targetting Android as a platform.
You might be able to compile to Java 1.5 (language level) using the 1.8 compiler; but then you may as well just use Java 1.5. (Keeping in mind that you still need to run you project through all the Android SDK steps need to deploy it on Dalvik: you can't just build a .jar as you would a regular Java app.)
This has been my experience - though I am not a full-time Android developer.
Not as far as I know.
You can use retrolambda project to use lambda expressions, but I don't know any project that back ported Optional's

When default methods will be supported (Java 8) in Android?

I was wondering if I can use default methods in interfaces in Android development.
The feature is included in Java 8, but I have found out that Android Java VM doesn't yet support it.
It there any way to use default methods in Android development? If not, when this feature will be available, is there some kind of timeline for this features?
On the availability: I think we'll see default methods in Android N. There are already a lot of tests related to default methods for the new Jack compiler on AOSP. See http://bit.ly/1PZoV1A
And today the java.util.function package has been merged into the ojluni master (including default methods and the use of lambdas).
Edit: Here is the official confirmation that Android N is going to support Java 8: http://developer.android.com/preview/j8-jack.html
Streams are still missing but java.util.Spliterator(s) has been integrated yesterday. Given the current pace, I'd expect we'll see the Stream API in May.
Possible duplicate : will android java support lambda expression in java 8?
In the possible duplicate question, kapep answered this (read the full answer for more details) :
Android doesn't use Oracle's Java SE versions, it's based on parts of the Apache Harmony project so it doesn't even support Java 7. Harmony is not actively developed any more and won't support 1.7.
So I think you can forget new features of Oracle Java version for Android development and follow the Android API (not the Oracle one).

Categories

Resources