├── .gitignore
├── .idea
└── androidDexCompiler.xml
├── AndroidManifest.xml
├── Java7-on-Android.iml
├── LICENSE
├── README.md
├── build.xml
├── building_with_ant
├── imgs
├── add-depend.png
├── addaslib.png
├── core-libs.png
├── corejar.png
├── lang-level.png
└── sdk-settings.png
├── libs
└── core.jar
├── project.properties
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── layout
│ └── main.xml
└── values
│ └── strings.xml
└── src
└── cc
└── TestActivity.java
/.gitignore:
--------------------------------------------------------------------------------
1 | gen
2 |
--------------------------------------------------------------------------------
/.idea/androidDexCompiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Java7-on-Android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012 Wes Lanning, http://codingcreation.com
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 | http://www.opensource.org/licenses/mit-license.php
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Using Java 7 & 8 Features on Android
2 |
3 | Feeling like you're stuck in 2006 while developing apps and libraries for Android?
4 |
5 | Don't worry, you're not alone. However, there's a solution!
6 |
7 | To help bring Android Java development into the modern era, I've tested and compiled a list of Java 7 and 8 features that will work on Android. Some of them, I discovered through a bit of testing and modding, while others depend on libraries maintained by others independently. Without further BS, here's a list of everything that can be used without issues on at least Android 2.2+.
8 |
9 | ## Google Now Officially Supports Java 7 on Android
10 |
11 | Starting with Android 4.4, [Google has declared officially](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Using-sourceCompatibility-1.7) that you can use Java 7 features with build-tools version 19. Directions for how to set it up with Gradle can be found on [tools.android.com](http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Using-sourceCompatibility-1.7).
12 |
13 |
14 | ## Possible (Working) Features
15 |
16 | * Try with resources (auto closing file handlers)
17 | * String switches
18 | * Multiple exceptions caught in one catch block
19 | * Integer (and binary) literals for readability
20 | * Type inference on collections (a.k.a. "diamonds")
21 | * [Java 8 lambdas thanks to Orfjackal (instructions coming soon)](https://github.com/orfjackal/retrolambda)
22 | * [Java 7 fork-join via JSR-166 (instructions coming soon)](http://gee.cs.oswego.edu/dl/concurrency-interest/index.html)
23 |
24 |
25 | ## Things that don't Work
26 |
27 | * Java 7 file API (java.nio.*) because some native code needs ported
28 | * File change notifications (watch/notify file api stuff)
29 | * Invoke Dynamic and features that rely on it (would require modifying Dalvik to support it)
30 |
31 |
32 | ## Setting up on Intellij IDEA 13 (and probably Android Studio)
33 |
34 | The new Intellij finally has a built in option to override core libraries of Android, making much of the above far easier. The instructions below take advantage of this and allow us to override the core libraries with a jar within Intellij IDEA normal build process. If using Intellij IDEA 12, you'll have to use the [old fallback instructions](https://github.com/yareally/Java7-on-Android/tree/master) as the directions for Intellij IDEA 13 will not work.
35 |
36 |
37 | 1. Clone this project or grab core.jar from the libs directory.
38 | 2. Enable overriding the Android core libraries by going to File → Settings → Compiler → Android Compilers
39 | 
40 | 3. Ensure core.jar is in your project library directory like below:
41 | 
42 | 4. Go to the File dropdown menu → Project Structure → Libraries and create a new library with core.jar:
43 | 
44 | 5. While still in the project setup area from above, go to "Modules" and add the newly created library as a project dependency. Ensure that it is placed above the Android SDK so that it overrides the Android SDK when necessary.
45 | 
46 | 6. Under the SDKs settings in the Platform Settings area, ensure you have an Android SDK set up to use at least Java 7 (Java 8 if you wish to use lambdas). Java 8 and Android are a bit quirky together in Intellij, so you may experience issues getting the Java 8 SDK to stick.
47 | 
48 | 7. The final setting to change under the project settings area is under "Project." Change the project language level to 7.0 (8.0 if you are going to use lambdas).
49 | 
50 | 8. Run this project's Android TestActivity to ensure everything is set up properly. If it does not run or you see syntax errors in Intellij, then ensure you settings looks similar to my screen shots.
51 |
52 |
53 | ## FAQ
54 |
55 | ### Does this really work on stock, unrooted/unmodified Android?
56 |
57 | Yup, because it's either using syntactic sugar features (which does not modify the bytecode) or it overrides the existing Android libraries.
58 |
59 |
60 | ### I'm having a problem unrelated to setting up the above configuration or running the provided example code.
61 |
62 | If you're having an issue related to either, feel free to file an issue and I will try to help you out when I have a few moments. If you are having an issue pertaining to lambdas or fork-join involving possible bugs in those libraries, please contact the maintainers of each project respectfully.
63 |
64 |
65 | ### Can I use Gradle with this?
66 |
67 | I still have to test it, but it'll probably work as long as you add the jar as a dependency in Gradle instead of under Intellij's build system. Don't forget to [enable the core library](imgs/core-libs.png) setting though. Gradle is also the recommended way to use Java 8 lambdas via [Evant's Gradle plugin](https://github.com/evant/gradle-retrolambda) until I find a method to do it without Gradle.
68 |
69 |
70 | ### Can I use Ant?
71 |
72 | If you need to use Ant, [I have a guide for that](https://github.com/yareally/Java7-on-Android/blob/master/building_with_ant).
73 |
74 |
75 | ### Won't this affect the entire Android System and not just my app?
76 |
77 | Since every Android app is sandboxed, only your code is affected.
78 |
79 |
80 | ### Do you have example code showing things working?
81 |
82 | Yes, please see the TestActivity included in this project.
83 |
84 |
85 | ### Will this work for other resource classes (like ObjectInputStream)?
86 |
87 | I'm sure it will, I just didn't include them in the jar. See the implemented InputStreams source as a template in the jar. I had to wrap them versus extending due to IDE complaints I was getting (in IDEA 12). Moving them to a separate module might solve that though or IDEA 13 may no longer require that (need to test it).
88 |
89 |
90 | ### Why doesn't Google implement these features themselves if they work?
91 |
92 | I don't work for Google and cannot answer that any better than any other non-employee. Perhaps eventually they will add them, but it's probably more likely they will add official support for a language alternative to Java first.
93 |
94 |
95 | ### Will this work on Eclipse/Netbeans/etc?
96 |
97 | Probably, but I don't really know how Android works on Eclipse/Netbeans, so you're on your own for that. If someone wishes to document the setup process for either, let me know and I will add it here when you're done. Aside from that, Ant works outside of Intellij, but [requires some modifying of the build.xml](https://github.com/yareally/Java7-on-Android/blob/master/building_with_ant) to override some of the compilation time stuff.
98 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
55 |
56 |
68 |
69 |
70 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/building_with_ant:
--------------------------------------------------------------------------------
1 | 1) Go to: /android-sdk-dir/tools/ant/build.xml and open it for editing.
2 |
3 | 2) Change:
4 |
5 |
6 |
7 |
8 | to:
9 |
10 |
11 |
12 |
13 |
14 | 3) Rename to something like so it uses
15 | the modified one in #4. Commenting it out will probably also work fine.
16 |
17 | 4) Override dex-helper with this modified macrodef (the important lines are --core-library and --no-strict):
18 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | 5) add the following path above the
56 |
57 |
58 |
59 |
60 | This will point to your project library so you can use the modded files as a jar.
61 | Make sure to name your jar file whatever you named it above (core.jar for this example).
62 | This file will go in your project_dir/libs directory.
63 |
64 | 6) Inside of
2 |
6 |
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | test2
4 |
5 |
--------------------------------------------------------------------------------
/src/cc/TestActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2012 Wes Lanning, http://codingcreation.com
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining
5 | a copy of this software and associated documentation files (the
6 | "Software"), to deal in the Software without restriction, including
7 | without limitation the rights to use, copy, modify, merge, publish,
8 | distribute, sublicense, and/or sell copies of the Software, and to
9 | permit persons to whom the Software is furnished to do so, subject to
10 | the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | http://www.opensource.org/licenses/mit-license.php
24 | */
25 |
26 | package cc;
27 |
28 | import android.app.Activity;
29 | import android.os.Bundle;
30 | import android.widget.Toast;
31 | import cc.io._BufferedInputStream;
32 | import cc.io._FileInputStream;
33 | import cc.io._FileOutputStream;
34 | import cc.test.R;
35 |
36 | import java.io.IOException;
37 | import java.lang.reflect.Method;
38 | import java.util.ArrayList;
39 | import java.util.Arrays;
40 | import java.util.List;
41 |
42 | public class TestActivity extends Activity
43 | {
44 | /**
45 | * Called when the activity is first created.
46 | */
47 | @Override
48 | public void onCreate(Bundle savedInstanceState)
49 | {
50 | super.onCreate(savedInstanceState);
51 | setContentView(R.layout.main);
52 |
53 | try {
54 | // obviously does not exist so our exception will be caught.
55 | Method multiCatchTest = getClass().getDeclaredMethod("doesNotExist");
56 | } catch (SecurityException | NoSuchMethodException | IllegalArgumentException e) {
57 | Toast.makeText(this,
58 | "Multicatch exception was caught, yay",
59 | Toast.LENGTH_LONG).show();
60 | }
61 |
62 |
63 | /* Java 8 won't work... */
64 | /* Runnable r2 = () -> {
65 | System.out.println("Second runnable");
66 | };
67 | r2.run();*/
68 | /* Comparator cmp = (x, y) -> (x < y) ? -1 : ((x > y) ? 1 : 0);
69 |
70 | if (cmp.compare(1, 2) == -1) {
71 | Toast.makeText(this, "1 is less than 2", Toast.LENGTH_LONG).show();
72 | }*/
73 |
74 |
75 | String[] months = {
76 | "JAN",
77 | "FEB",
78 | "MAR",
79 | "APR",
80 | "MAY",
81 | "JUN",
82 | "JUL",
83 | "AUG",
84 | "SEP",
85 | "OCT",
86 | "NOV",
87 | "DEC"};
88 |
89 | int m = getRandomMonth(12);
90 |
91 | Toast.makeText(this,
92 | String.format(
93 | "%s has %d days in its month.",
94 | months[m],
95 | getDaysInMonth(months[m])),
96 | Toast.LENGTH_LONG).show();
97 |
98 | // showing "try with resources"
99 | try (_FileOutputStream fos = new _FileOutputStream("/sdcard/testfile.txt")) {
100 | // integer literals work, yay
101 | Toast.makeText(this,
102 | String.format(
103 | "Shown as 1_000 and 2_000 in the IDE, but shown as %d %d in Android as they should",
104 | 1_000, 2_000),
105 | Toast.LENGTH_LONG).show();
106 |
107 | // binary literal also works
108 | byte[] writeData = {
109 | (byte) 0b0101_1110, (byte) 0b1000_0000
110 | };
111 |
112 | fos.write(writeData);
113 | Toast.makeText(this,
114 | String.format(
115 | "Written to testfile.txt: %s",
116 | Arrays.toString(writeData)),
117 | Toast.LENGTH_LONG).show();
118 | } catch (IOException ioe) {
119 | Toast.makeText(this,
120 | String.format(
121 | "Error: %s",
122 | ioe.getMessage()),
123 | Toast.LENGTH_LONG).show();
124 | }
125 |
126 | try (_BufferedInputStream fis = new _BufferedInputStream( new _FileInputStream("/sdcard/testfile.txt"))) {
127 | // to show "diamonds" working
128 | List readData = new ArrayList<>(4);
129 | int nextInt;
130 |
131 | while ((nextInt = fis.read()) != -1) {
132 | readData.add(String.valueOf(nextInt));
133 | }
134 |
135 | Toast.makeText(
136 | this,
137 | String.format(
138 | "Read data from testfile.txt: %s",
139 | readData.toString()),
140 | Toast.LENGTH_LONG).show();
141 | } catch (IOException ioe) {
142 | Toast.makeText(this,
143 | String.format(
144 | "Error: %s",
145 | ioe.getMessage()),
146 | Toast.LENGTH_LONG).show();
147 | }
148 | }
149 |
150 | /**
151 | * Demonstrates that string switches are working.
152 | *
153 | * @param month
154 | * @return
155 | */
156 | public static int getDaysInMonth(String month)
157 | {
158 | switch (month) {
159 | case "JAN":
160 | return 31;
161 | case "FEB":
162 | return 28;
163 | case "MAR":
164 | return 31;
165 | case "APR":
166 | return 30;
167 | case "MAY":
168 | return 31;
169 | case "JUN":
170 | return 30;
171 | case "JUL":
172 | case "AUG":
173 | return 31;
174 | case "SEP":
175 | return 30;
176 | case "OCT":
177 | return 31;
178 | case "NOV":
179 | return 30;
180 | case "DEC":
181 | return 31;
182 | default:
183 | return 0;
184 | }
185 | }
186 |
187 | public static int getRandomMonth(int limit)
188 | {
189 | return (int) (Math.random() * limit);
190 | }
191 | }
192 |
--------------------------------------------------------------------------------