Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Google supports Java 7 features on Android (android.com)
56 points by yareally on Nov 11, 2013 | hide | past | favorite | 12 comments


Officially relying on "try with resources" for Android 4.3 and before can be hit or miss, depending whether the OEM added it to the build for the device or not, so just a fair warning.

A way to overcome the issue with "try with resources" is to add the missing JDK7 source files[1] yourself to your build and enable "--core-libraries" found under settings → Compiler → Android Compilers in Intellij IDEA 13 and Android Studio. The "--core-libraries" option allows your app to use any system libraries you may include instead of those on the device. It's a dex compiler option that's been around for a while, but was much more painful to enable prior to a recent update to IDEA 13.

[1] From the Android SDK v19 sources, take java.lang.AutoCloseable, java.lang.Throwable and any of the Stream Classes you wish to use that implement AutoCloseable (such as java.io.BufferedInputStream)

Edit: Forgot to mention the stream classes that implement AutoCloseable are also required for the 4.3 and before to use the workaround.


Statically including system libraries with an application just to be able to use a convenience feature of a language seems pretty dangerous. What if Google finds and fixes a bug in one of those classes in an Android version update?


Since it could set it up so you're only overriding system files for Android versions older than 4.4. Any bug fixes, would be part of the system core are only going to be in updated with Android 4.4+, which is not using the backported classes. If doing that, don't see it ever being an issue.

This is a little rough and there may be a better way, as it's 7am here right now and looking at the SDK source is not something I want to do at this hour, but something like this should work, making your own "Android support library":

1) Use multiple dex files[1] in an apk and dynamically load the backported library files based on whether the app is using 4.3 and before or 4.4+.

or

2) Mess around with the source files, which is much more ugly:

- Change Throwable to your app package domain, leaving the class name the same. This will likely require changing some other exception classes to do the same as well.

- Leave Closable and AutoCloseable in the system package domain within your app, as each is just a one method interface and will make things more complicated if you move them, but they could also be changed if refactored in the backported stream files.

- Change the backported AutoClosing streams to your app package domain. Make a wrapper for each to check if you're on 4.3 and before and call to your modded stream backported files or 4.4+ and call to the system ones. The key would be ensuring it uses the proper Throwable class, since that is where things happen.

- Add to the Streams some conditions to check if the app is installed on Android 4.4+ and use the system classes with the OS or 4.3 and use your backported classes.

[1] http://android-developers.blogspot.com/2011/07/custom-class-...

Edit: Remembered you could load a library from a separate dex file and dynamically load it.


> Since it could set it up so you're only overriding system files for Android versions older than 4.4...

I note that, to do this, you would have to publish (at least) two APKs using the multiple APK mechanism (http://developer.android.com/google/play/publishing/multiple...), which seems like quite a hassle.


I revised my post to be more clear about how it would be done so no need for that I don't think if minimizing what one is directly overriding in the system classes.

EDIT: I forgot that multiple dex files can be included in an apk[1] as well and dynamically loaded. That may be the most elegant solution. To just package it as as separate dex file and dynamically load it if on Android 4.3 or older.

[1] http://android-developers.blogspot.com/2011/07/custom-class-...


That's interesting. As far as I remember, it's not possible to use any Java 7 language features while compiling to class files compatible with the 1.6 JRE with "regular" Java. (See e.g. http://stackoverflow.com/questions/17168184/java-7-language-...)


The title of the section is using Java 7 source compatibility, so I don't think it is about compiling to be compatible with 1.6, it's compiling to be compatible with 7. Realistically, Android code doesn't get run on a JVM anyway, so the whole thing is kind of silly. If their translation to DEX byte code supports only 1.6 class files, then it supports only 1.6, but clearly it supports 7 now.


Try-with-resources requires library compatibility. All other Java 7 features can be expressed using Java 6 bytecode structures, so it doesn't surprise me that they're allowing them in pre-KitKat projects.


But does it actually support invokedynamic?

I saw that https://android-review.googlesource.com/#/c/58880/ was merged a while ago, but I'm not sure if any other commits have improved things further.


Not sure yet, but I'll test and see at some point. I only stumbled on the actual support evidence shortly before submitting the link to HN.


If you plan to check, I won't bother (I had also planned to investigate later). You should also check on MethodHandles, since (as of the commit I linked) their parser also threw exceptions when it came across them.

If these things don't work, I'm very disappointed in the Android team, as this would be totally fake v51 classfile support.


Tried a small invoke example, there seems to be no java.lang.invoke.* package in Android API 19 and also no MethodHandle class.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: