Java 7 language features with Android
If you are using Android Studio, the Java 7 language should be enabled automatically without any patches. Try-with-resource requires API Level 19+, and NIO 2.0 stuff are missing.
If you can't use Java 7 features, see @Nuno's answer on how to edit your build.gradle
.
The following is for historical interest only.
A small part of Java 7 can certainly be used with Android (note: I have only tested on 4.1).
First of all, you could not use Eclipse's ADT because it is hard-coded that only Java compiler 1.5 and 1.6 are compliant. You could recompile ADT but I find there is no simple way to do that aside from recompiling the whole Android together.
But you don't need to use Eclipse. For instance, Android Studio 0.3.2, IntelliJ IDEA CE and other javac-based IDEs supports compiling to Android and you could set the compliance even up to Java 8 with:
- File → Project Structure → Modules → (pick the module at the 2nd pane) → Language level → (choose "7.0 - Diamonds, ARM, multi-catch, etc.")
This only allows Java 7 language features, and you can hardly benefit from anything since a half of improvement also comes from the library. Features you could use are those which do not depend on the library:
- Diamond operator (
<>
) - String switch
- Multiple-catch (
catch (Exc1 | Exc2 e)
) - Underscore in number literals (
1_234_567
) - Binary literals (
0b1110111
)
And these features cannot be used yet:
- The
try
-with-resources statement — because it requires the non-existing interface "java.lang.AutoCloseable" (this can be used publicly in 4.4+) - The @SafeVarargs annotation — because "java.lang.SafeVarargs" does not exist
... "yet" :) It turns out that, although Android's library is targeting for 1.6, the Android source does contain interfaces like AutoCloseable and traditional interfaces like Closeable does inherit from AutoCloseable (SafeVarargs is really missing, though). We could confirm its existence via reflection. They are hidden simply because the Javadoc has the @hide
tag, which caused the "android.jar" not to include them.
There is already as existing question How do I build the Android SDK with hidden and internal APIs available? on how to get those methods back. You just need to replace the existing "android.jar" reference of the current Platform with our customized one, then many of the Java 7 APIs will become available (the procedure is similar to that in Eclipse. Check Project Structure → SDKs.)
In additional to AutoCloseable, (only) the following Java 7 library features are also revealed:
- Exception chaining constructors in ConcurrentModificationException, LinkageError and AssertionError
- The static .compare() methods for primitives: Boolean.compare(), Byte.compare(), Short.compare(), Character.compare(), Integer.compare(), Long.compare().
- Currency: .getAvailableCurrencies(), .getDisplayName() (but without .getNumericCode())
- BitSet: .previousSetBit(), .previousClearBit(), .valueOf(), .toLongArray(), .toByteArray()
- Collections: .emptyEnumeration(), .emptyIterator(), .emptyListIterator()
- AutoCloseable
- Throwable: .addSuppressed(), .getSuppressed(), and the 4-argument constructor
- Character: .compare(), .isSurrogate(), .getName(), .highSurrogate(), .lowSurrogate(), .isBmpCodePoint() (but without .isAlphabetic() and .isIdeographic())
- System: .lineSeparator() (undocumented?)
- java.lang.reflect.Modifier: .classModifiers(), .constructorModifiers(), .fieldModifiers(), .interfaceModifiers(), .methodModifiers()
- NetworkInterface: .getIndex(), .getByIndex()
- InetSocketAddress: .getHostString()
- InetAddress: .getLoopbackAddress()
- Logger: .getGlobal()
- ConcurrentLinkedDeque
- AbstractQueuedSynchronizer: .hasQueuedPredecessors()
- DeflaterOutputStream: the 3 constructors with "syncFlush".
- Deflater: .NO_FLUSH, .SYNC_FLUSH, .FULL_FLUSH, .deflate() with 4 arguments
That's basically all. In particular, NIO 2.0 does not exist, and Arrays.asList is still not @SafeVarargs.
EDIT: At the time this was written, the latest release was Android 9 and Eclipse Indigo. Thing have changed since then.
- Practical answer
Yes, I have tried. But this is not a great test as the compatibility was limited to level 6 with no way (no simple way at least) to really use java 7:
- First I installed a JDK7 on a machine that had no other JDK installed - Eclipse and Android are not installed either:
- Then I installed a brand new Eclipse Indigo and checked it was actually using the JDK 7 (well, as this is the only one and as this is the one I've selected I would have been surprised)
Then I installed the latest version of the Android SDK (EDIT: Honeycomb, API13, at the time this post was written). It found my JDK 7 and installed properly. The same for ADT.
But I had a surprise when trying to compile and run a Hello Word Android app. The compatibility was set to Java 6 with no way to force it to Java 7:
- I tried with a non-Android project, a regular Java one, and I had the explanation. The compatibility level seems to be limited by Eclipse (see the message at bottom of the following image):
So I had Hello World working, and also other apps, more complicated and using SQLite
, Listview
, Sensor
and Camera
, but this only proves that the compatibility handling of Java 7 seems to be well done and working with Android.
So, did someone try with the good old Ant, to bypass the Eclipse limitation seen above?
- Theroetical answer
Anyway, the SDK is designed to be used with Java 5 or 6, as explained here.
We may have something working with Java 7, but it would be working "by accident". The building of the DEX may work properly or not, and once the DEX built, it may work or not. This because using a non-qualified JDK gives unpredictable results by definition.
Even if someone has succesfully built an Android app under plain Java 7, this does not qualify the JDK. The same process applied to another application may fail, or the resulting application may have bugs tied to the use of that JDK. Not recommended.
For those who are involved on webapps development, this exactly the same as deploying a web application built under Java 5 or 6 under an application server qualified for Java 4 only (let's say Weblogic 8 for example). This may work, but this is not something that can be recommended for other purposes than trying.