- Using SDKMAN! to work with multiple versions of Java
- Installing SDKMAN!
- Installing a specific version of Java
- Switching between Java versions
- Installing other tools
- Using SDKMAN! with an IDE
- Happy Hacking!
- Build failed error: cannot find symbol if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
- Which Java version for Android with different minSdkVersion and targetSdkVersion
- 1 Answer 1
- How can I check the system version of Android?
Using SDKMAN! to work with multiple versions of Java
If you code in Java, you might be coding against Java 11, or 8, or maybe an even older version. You may also be prototyping code against newer versions of Java, the current version is 13. Java 14 will be released this month, and 15 later this year. At the same time, you might be investigating different builds of OpenJDK — there are several free alternatives. I use AdoptOpenJDK’s builds of OpenJDK which is an increasingly popular choice according to the JVM Ecosystem Report 2020.
You could also be trying out different build tools like Maven and Gradle. I use both, depending on the project.
Put bluntly, managing all this can be difficult. It’s not impossible to manage by hand, but it’s fiddly and if you get it wrong the error messages can be hard to understand.
Enter SDKMAN! It’s a tool for managing the installation and selection of Software Development Kits — not just different versions and builds of Java itself, but tools for building, debugging, monitoring, documenting and deploying too. It is available for Windows, Linux and MacOS.
Installing SDKMAN!
Follow the installation instructions for your platform. If you use the terminal a lot, I highly recommend checking out Oh My Zsh which can add a ton of useful information and behaviour. There is an SDKMAN! plugin for Oh My Zsh which adds tab completion to the sdk command which is really helpful. Enable this by finding the plugins= line in the .zshrc file in your home directory and adding sdk . Mine reads:
If you do edit that file you’ll need to reload the Zsh config with source ~/.zshrc .
Installing a specific version of Java
Let’s say we want to install the latest build of Java 11 from AdoptOpenJDK. First of all let’s check that it’s available, using sdk list java . If you’ve set up Oh My Zsh this is tab-completable:
So the latest Java 11 OpenJDK build from AdoptOpenJDK has the identifier 11.0.6.hs-adpt . Install it with:
sdk install java 11.0.6.hs-adpt
SDKMAN! will download that version of Java, and unzip it into a directory on your computer. You don’t need to worry about exactly where, because SDKMAN! will also update environment variables so that you can use java in the terminal immediately:
➜ java -version openjdk version "11.0.6" 2020-01-14 OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10) OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.6+10, mixed mode)
Switching between Java versions
I’ve also installed the latest early-access version of Java 14 (due to be released March 17th 2020) so that I can try out some of the new features. I did that with:
sdk install java 14.ea.36-open
I said “no” when it asked if I wanted to use that as the default version. Later on, switch between them using sdk use java :
I think you would agree that this is a lot easier than managing downloads, installations and environment variables by hand.
You can see what version you are using right now with sdk current :
➜ sdk current Using: java: 14.ea.36-open
Installing other tools
For different projects I use either Maven or Gradle as my build tool, and for debugging and profiling I sometimes use VisualVM. Install the latest versions of these with:
sdk install maven 3.6.3 sdk install gradle 6.2.2 sdk install visualvm 2.0
And they’re instantly available.
Using SDKMAN! with an IDE
To select a particular version of Java for a project in IntelliJ IDEA or Eclipse, you will need to know exactly where SDKMAN! has unpacked your Java installations. This is $HOME/.sdkman/candidates/java , with subdirectories named after the versions. The currently selected version of Java will also be available as current in that directory:
➜ ls -l ~/.sdkman/candidates/java total 8 drwxr-xr-x 10 mjg mjg 4096 Jan 15 12:14 11.0.6.hs-adpt drwxrwxr-x 8 sdk mjg 4096 Mar 4 12:43 14.ea.36-open lrwxrwxrwx 1 mjg mjg 52 Mar 4 12:35 current -> /home/mjg/.sdkman/candidates/java/14.ea.36-open
I recommend keeping things clearer by configuring projects in your IDE to use a specific installation, rather than “current”.
For IntelliJ IDEA this can be done from the “Project Structure” dialog. Either choose an existing version from the drop-down, or add a new Java version by selecting “New. ” from the “Project SDK” section:
For Eclipse, this is done by heading to “Project Properties”, then “Java Build Path”, “Libraries” and selecting “Modulepath”:
You should select the version that’s there already (11.0.6.hs-adpt in this example) and remove it, then select “Modulepath” again, “Add Library” and select “JRE System Library” from the dialog:
In the “Add Library” dialog, select “Alternate JRE” and click “Installed JREs” to open another dialog which lets you choose an existing version, or add a new Java installation by browsing to where it is installed:
Happy Hacking!
Using SDKMAN! can save you a lot of time and trouble if you work with multiple versions of Java and related tools. Maybe use that time to check out how to build cool things with Java and Twilio like a WhatsApp bot which does image recognition or sending daily SMS reminders?
I’d love to hear what you’re building, tell me about it on Twitter @MaximumGilliard or by email on mgilliard@twilio.com, or post it on Reddit to /r/twilio for the whole world to see.
- Matthew Gilliard
- About
- Legal
- Copyright © 2023 Twilio Inc.
- All Rights Reserved.
- Protected by reCAPTCHA – Privacy – Terms
Build failed error: cannot find symbol if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
C:\incidentApp\platforms\android\app\src\main\java\com\moust\cordova\videoplayer\VideoPlayer.java:123: error: cannot find symbol if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) < ^ >Task :app:compileDebugJavaWithJavac symbol: variable R location: class VERSION_CODES C:\incidentApp\platforms\android\app\src\main\java\com\moust\cordova\videoplayer\VideoPlayer.java:124: error: cannot find symbol dialog.getWindow().getInsetsController().hide(WindowInsets.Type.statusBars()); ^ symbol: variable Type location: class WindowInsets C:\incidentApp\platforms\android\app\src\main\java\com\moust\cordova\videoplayer\VideoPlayer.java:124: error: cannot find symbol dialog.getWindow().getInsetsController().hide(WindowInsets.Type.statusBars()); ^ symbol: method getInsetsController() location: class Window Note: Some input files use or override a deprecated API. Note: Recompile with -Xlint:deprecation for details. Note: Some input files use unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. 3 errors FAILURE: Build failed with an exception. Task :app:compileDebugJavaWithJavac FAILED 24 actionable tasks: 1 executed, 23 up-to-date
Compilation failed; see the compiler error output for details.
- Try: Run with —stacktrace option to get the stack trace. Run with —info or —debug option to get more log output. Run with —scan to get full insights.
- Get more help at https://help.gradle.org
FAILURE: Build failed with an exception.
Compilation failed; see the compiler error output for details.
I’d tried everything(removing of android package and re-installing) I could lay my hands on but still not working.
Below is my build.gradle
Which Java version for Android with different minSdkVersion and targetSdkVersion
When using Gradle to compile my Android applications, how do I determine which Java version to use? For instance, some snippets of my gradle build file look like:
Java SE 7 is supported for android SDK version 19 and higher, that is for KitKat and above. Given the above snippet, how do I determine whether I should use Java SE 7 or Java SE 6 for compilation and source code compatibility?
1 Answer 1
Neither the minSdkVersion nor the targetSdkVersion are used to determine the source code compatibility for compilation. The determinant for source compatibility and compilation is both the compileSdkVersion and buildToolsVersion .
I used a gradle file with the following values:
A snippet of the code specifically used for test is:
public void onCreate(Bundle bundle) < . Liststrings = new ArrayList<>(); strings.add("John Doe"); strings.add("Jane Doe"); strings.add("Bill Gates"); strings.add("Mark Zuckerberg"); ListView listView = (ListView) findViewById(R.id.list); ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_gallery_item, strings); listView.setAdapter(adapter); . >
When you change the build tools to buildToolsVersion = ’17’ you get an error message:
The SDK Build Tools revision (17.0.0) is too low for project ':app'. Minimum required is 19.1.0
When you change this to buildToolsVersion = ‘19.1.0’ , the build is successful.
When you set the compileSdkVersion to any value less than the buildToolsVersion major value, build fails, mainly due to missing resource dependencies.
Setting the minSdkVersion and targetSdkVersion to any version below the compileSdkVersion has no effect.
P.S. 1. Major value is the first integer before the first dot. e.g. buildToolsVersion ‘23.0.2’ has major value is 23.
P.S. 2. I tested the results of a successful build with a real device with Android API Level 10, (Gingerbread 2.3.6). I set source code compatibility to JDK 7, and used the Diamond Operator introduced in Java 7.
How can I check the system version of Android?
I totally ignore any older version than Eclair (7), Android 2.1 and very soon we stop support for the 2.1 also. But you can use the SDK instead of SDK_INT.
I have a question: if it is running on a system older than GINGERBREAD, then we can not get android.os.Build.VERSION_CODES.GINGERBREAD, will the app crash?
No, because GINGERBREAD will by replaced by just the number during the java build. It is only necessary to use bigger compile version of Android.
- CODENAME : The current development codename, or the string «REL» if this is a release build.
- INCREMENTAL : The internal value used by the underlying source control to represent this build.
- RELEASE : The user-visible version string.
The hard part about this is that SDK_INT has been defined in API Level 4 and using it fails on 1-3. Does anybody know how to nicely deal with that?
Build.Version is the place go to for this data. Here is a code snippet for how to format it.
public String getAndroidVersion()
Looks like this «Android SDK: 19 (4.4.4)»
For checking device version which is greater than or equal to Marshmallow ,use this code.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)
for ckecking others just change the VERSION_CODES like,
K for kitkat,
L for loolipop N for Nougat and so on.
That will give you the actual numbers of your version; aka 2.3.3 or 2.2. The problem with using Build.VERSION.SDK_INT is if you have a rooted phone or custom rom, you could have a none standard OS (aka my android is running 2.3.5) and that will return a null when using Build.VERSION.SDK_INT so Build.VERSION.RELEASE will work no matter what!
From SDK: «The user-visible version string. E.g., «1.0» or «3.4b5″.» . «3.4b5» how can I determine which version number is it ?
The whole answer 2.3.3 is the version number, or 2.2, or 2.3.5 (custom rom in my case). That is the OS Version number as a whole.
It returns the same thing Menu >> Settings >> About Phone. It should be labeled Firmware Version or something to that affect.
You can find out the Android version looking at Build.VERSION .
The documentation recommends you check Build.VERSION.SDK_INT against the values in Build.VERSION_CODES .
This is fine as long as you realise that Build.VERSION.SDK_INT was only introduced in API Level 4, which is to say Android 1.6 (Donut). So this won’t affect you, but if you did want your app to run on Android 1.5 or earlier then you would have to use the deprecated Build.VERSION.SDK instead.
I can’t comment on the answers, but there is a huge mistake in Kaushik’s answer: SDK_INT is not the same as system version but actually refers to API Level.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) < //this code will be executed on devices running ICS or later >
The value Build.VERSION_CODES.ICE_CREAM_SANDWICH equals 14. 14 is the API level of Ice Cream Sandwich, while the system version is 4.0. So if you write 4.0, your code will be executed on all devices starting from Donut, because 4 is the API level of Donut ( Build.VERSION_CODES.DONUT equals 4).
if(Build.VERSION.SDK_INT >= 4.0) < //this code will be executed on devices running on DONUT (NOT ICS) or later >
This example is a reason why using ‘magic number’ is a bad habit.