Android Studio: 1.3.1 - Gradle Build Plugin: 1.1.2 - Gradle: 1.3.0
On Android Studio, I have an app that runs perfectly fine on Android API22 (Lollipop, on both simulator API22 and Android phone API22, and also works on API 21 - but nothing below API 21).
In my Gradle build file, I have the following:
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 17
targetSdkVersion 22
...
compile "commons-io:commons-io:2.4" //IO
So, as I understand it: my app is compiled with the latest API (22) to run on devices from API 17 to API 22 (and 22+ in compatibility mode).
However, when I run the Android app on a API 17 simulator, it crashes during some file copy operations.
Before the crash, dalivkvm complains it cannot find methods.
I/dalvikvm﹕ Could not find method org.apache.commons.io.FileUtils.copyInputStreamToFile,
referenced from method FileCopy.batchCreate
W/dalvikvm﹕ VFY: unable to resolve static method 58205: Lorg/apache/commons/io/FileUtils;
.copyInputStreamToFile (Ljava/io/InputStream;Ljava/io/File;)V
D/dalvikvm﹕ VFY: replacing opcode 0x71 at 0x0058
Then the fatal exception:
E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NoClassDefFoundError: org.apache.commons.io.FileUtils
Now obviously the apache commons libraries can be present and imported, at least on API 22 (which, I remind you, runs successfully on both the device and the simulator).
This also happens for other libraries aside from the Apache commons one (if I skip using the Apache Commons, then another third party library will cause a similar issue and so on).
I'm at loss as to why it won't run on API 17. Also have the same issues on API 18 and 19, API 20 doesn't exist.
It appears to work correctly on both API 21 and API 22.
I've looked for similar errors on here, but usually it is because people simply forgot to include their jar libs so it didn't help.
UPDATES
MultiDex is enabled. On API 21 (Lollipop) the way multidex is supported has changed (see https://developer.android.com/tools/building/multidex.html). So it might have something to do with this.
Gradle builds Modules in "release mode" when app is in "Debug mode" (Why does Gradle build my module in Release mode when the app is in Debug)
I tried rebuilding, creating a new project with the files to no avail.
The "commons-io:commons-io:xxx" folder is present in the Gradle cache folder.
I was able to fix my own issue.
So essentially, as I understand it (but I don't have time to investigate further), the issue is due to the fact that the way "Multidex" is supported has changed in Android API 21 (aka Android 5.0).
The link: https://developer.android.com/tools/building/multidex.html tells us:
Android 5.0 and higher uses a runtime called ART which natively
supports loading multiple dex files from application APK files.
Now, it would seem that when multidexing and trying to support both "normal DEXing" (before 5.0/API21) and "ART oat files" (the new "DEX" files after 5.0/API21) in the same application you can encounter some issues similar to mine (unable to find some methods before API21 but app working fine on API21 and above).
My app hit the 65k methods limit and I had to support from API17+.
Anyway, the workaround was to disable multidex and use instead minifyEnabled with "Proguard", so that all unused methods are removed by Proguard and the total number of methods ends up below 65k.
The associated code (in Gradle build file):
defaultConfig {
...
//Enabling multidex support (for more than 65k methods)
multiDexEnabled false
}
buildTypes {
debug {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
This isn't a real solution, of course, as someone who needs to effectively use 65k methods will HAVE to use multidex, but it did the job nicely for me and I can't spend more time on these issues.
Hopefully this will help someone.
Related
I am getting the following error:
"
The SDK platform tools version (25.0.6) is too old to check APIs
compiled with API 26; please update This check scans through all
ANDroid API calls in the application and warns about any calls that
are not available on all versions targeted by the application
(according to its minimum SDK attribute in the manifest). If you
really want to use this API and don’t need to support older devices
just set the minSdkVersion in the build.gradle or AndroidManifest.xml
files If your code is deliberately accessing newer APIs and you have
ensured (e.g. with conditional execution) that this code will only
ever be called on a supported platform, then you can annotate you
class or method with the #TargetApi annotation specifying the local
minimum SDK to Apply, such as #TargetApi(11), such that this check
considers 11 rather than you manifest file’s minimum SDK as the
required API level. If you are deliberately setting android:
attributes in style definitions, make sure you place this in
values-xxx folder in order to avoid running into runtime conflicts on
certain devices where manufacturers have added custom attributes whose
ids conflict with new ones or later platforms. Similarly, you can use
tooltargetApi=”11” in an XML file to indicate that the elements will
only be inflated in an adequate context."
I also get the package name up top as an error, but I just created the new App and even though it indicates an error. The source code compiles and runs on the emulator on the targeted device.
Go to your App Level Gradle file and enter the following:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion '26.0.0'
defaultConfig {
applicationId ">>>YOURPACKAGENAME<<<"
minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
I have an application project with this settings:
android {
compileSdkVersion 21
buildToolsVersion '19.1.0'
defaultConfig {
minSdkVersion 10
targetSdkVersion 19
}
buildTypes {
release {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
And I have a block with try-with resources which not use checking if Build.SDK is less than API 19.
I don't get any errors from IDE about it.
I ran a program on emulator with target SDK Android 4.1.2 and everything is fine, also checked on the device with Android 4.2.2. The program is invoke this code, checked with the debugger.
Is everything ok? I expect that there is might be compatibility errors from IDE but there's not.
If I try to create a new project in IDE with same minVersionSdk 10, I've got a error from IDE about the compatibility.
But in my working project I don't get it.
I don't know, is there any other settings for compatibility, not in build.gradle and AndroidManifest.xml? Why is it working on API < 19 ?
UPDATE:
you need to check Lint settings in Android Studio.
Editor - Inspections
Android Lint, Calling new methods on older versions
Why is it working on API < 19 ?
According to this: https://code.google.com/p/android/issues/detail?id=73483 It "mostly works" from API 15, and you tested on an API 16 emulator (4.1.2).
Issue raiser states:
Since it was unhidden in API level 19, try-with-resources is backwards compatible down to API level 15.
Google member replies (edited down):
AutoCloseable was in ics. and it's just an interface; it's javac that emits code to actually do the closing. iirc there are fewer classes that are AutoCloseable in ics than we actually unhid
so "backwards compatible" is a bit misleading. "mostly works" is closer to the truth.
Because it's not fully compatible, the warning is from API 19.
As to why you are not seeing the warning, I think that is down to your very old buildToolsVersion which dates back to December 2013. https://developer.android.com/tools/revisions/build-tools.html
You should always keep your Build Tools component updated by downloading the latest version using the Android SDK Manager
If you only use methods which were created before API 10 (You can check here) everything is ok.
If you are not sure, you can run lint (by right clicking on your root folder) and then you can check if lint warn you about deprecated method usage.
If you want more explanation don't hesitate to comment
My application has a bunch of librarys that are essential that is why I was forced to use multidex support library and it works nicely. But where the problem shows is in the gradle buid speed. It takes on average 2minutes to build and when I am developing and testing this is quite annoying.
Is there a way to speed up my debug builds?
You can speed-up your development builds by specifying the minimum SDK version = 21.
Official documentation includes a whole section about that.
Example (from documentation):
android {
productFlavors {
// Define separate dev and prod product flavors.
dev {
// dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
// to pre-dex each module and produce an APK that can be tested on
// Android Lollipop without time consuming dex merging processes.
minSdkVersion 21
}
prod {
// The actual minSdkVersion for the application.
minSdkVersion 14
}
}
...
buildTypes {
release {
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}
Once you added the product flavors, you can use the devDebug task (instead of default debug task) for your development builds:
- from command line: run ./gradlew installDevDebug
- from Android Studio: open Build Variants window and select the devDebug build variant.
You should, of course, work against a device whose SDK >= 21.
There's also a solution for those who don't want to use flavors. As suggested in this gist, dynamically calculate the minSdkVersion value:
int minSdk = hasProperty('devMinSdk') ? devMinSdk.toInteger() : 14
apply plugin: 'com.android.application'
android {
...
defaultConfig {
minSdkVersion minSdk
...
}
}
In this example, we're checking if devMinSdk property defined, and if true - we're using it. Otherwise, we default to 14.
How do we pass devMinSdk value to build script? Two options:
Using command line:
./gradlew installDebug -PdevMinSdk=21
Using Android Studio preferences:
Go to Preferences (Settings on Windows) -> Build, Execution, Deployment -> Compiler -> put -PdevMinSdk=21 in Command-line Options text box.
Recently build cache was introduced by team working on Android Gradle plugin. You can enable it by adding android.enableBuildCache=true to gradle.properties.
More info here
http://tools.android.com/tech-docs/build-cache
For me it increased incremental build times by ~30 seconds.
It doesn't work with legacy multidex (com.android.support:multidex) introduced as part of support library, so it's suitable only if your minSDK >= 21. You can set it only for your your development builds and do release builds with minSDK < 21.
It also works without multidexing enabled.
Android Studio 1.3 (currently in Preview 3) is using a new build system which improved gradle build time (really, like 10-30x faster).
More information in the Live Session at Google I/O 2015
Multidexing uses more memory. As you get closer to your max heap size in Java you'll find Java spends more time doing GC than it does doing any real work, this can slow things down a lot.
I'd strongly recommend increasing the max heap size when using multidex. Add the following to the android closure in your build.gradle file to make the max heap size 4GB (Make it smaller if you wish):
dexOptions {
javaMaxHeapSize "4g"
}
Changing MinSdk to 21 made everything back to normal for me.Now everything compiles in like 6s
This is no longer needed with the latest Android Studio 3.0
Go in setting , search compiler , type "--offline" in Command line options and than compile.
I am trying to build Multidex apk in eclipse, and not able to succeed.
I tried following steps, for configuring Multidex support in android app:
I have added the Multidex library located at /extras/android/support/multidex/ to my project.
As my app is having custom application class, I have extended android.support.multidex.MultiDexApplication Class to my application.
Still i am not able to build apk.
Android developer is also not having any documentation for building Multidex apk in eclipse, its only having documentation for gradle and Android Studio.
You have to modify build.gradle to add multiDexEnabled true under buildconfig, buildType or productFlavour sections
defaultConfig {
// The support library goes as back as Android-14, and is not required for 21+
minSdkVersion 14
// Enabling multidex support.
multiDexEnabled true
}
If you're building on old Ant, this is a blocking problem so you'll have to move to gradle or maven or use the old cumbersome solution
http://android-developers.blogspot.com.es/2011/07/custom-class-loading-in-dalvik.html
I try to inject support libraries into my Android Studio project.
If I try anything lower than 20 it says:
library should not use a lower version then targetSdk version.
If I use compile 'com.android.support:support-v4:20' I get:
Failed to find: com.android.support:support-v4:20
If I use compile 'com.android.support:support-v7:20.0.+' I get:
Avoid using + in version numbers, can lead to unpredictable and unrepeatable builds.
So the simple question is:
where can I find up-to-date, ready to use, version numbers that Do work?
If I try anything lower than 20 it says: library should not use a lower version then targetSdk version.
That is because you set your targetSdkVersion to something higher than 19. If you did so intentionally, fine. If you did not do so intentionally, consider dropping it back to 19 for now, and use compile 'com.android.support:support-v4:19.1.0' (if you are using the backport of fragments) or compile 'com.android.support:support-v13:19.1.0' (if you are not using the backport of fragments).
If I use compile 'com.android.support:support-v4:20' I get: Failed to find: com.android.support:support-v4:20
That is because the Android Support package uses X.Y.Z semantic versioning, as do most artifacts in repositories. 20 does not match the X.Y.Z pattern.
If I use compile 'com.android.support:support-v7:20.0.+' I get: Avoid using + in version numbers, can lead to unpredictable and unrepeatable builds.
That is merely a warning. If you are using version control for your project files, and you feel that it is important to be able to check out some earlier version of your code and be able to reproduce that build, then using the + notation is not a good idea. OTOH, if being able to reproduce historical builds is not essential, using the + wildcard, as you are doing, ensures that you get updates automatically. Having the + in the third position (Z in X.Y.Z) means that you will automatically get patchlevel updates.
where can I find up-to-date, ready to use, version numbers that Do work?
On your hard drive, in $ANDROID_SDK/opt/extras/android/m2repository/com/android/support/$LIBRARY/, where $ANDROID_SDK is wherever you installed the Android SDK and $LIBRARY is whichever Android Support package library you are interested in (e.g., support-v13).
To see the current Android Support Library revision number ...
Android Studio > Tools > Android > SDK Manager ...
Extras > Android Support Library: See the Rev. number e.g. (21.0.3).
For a quick insertion of the right revision number when in your gradle file you currently have something like 'com.android.support:appcompat-v7:21.0.+' with the 'Avoid using + in version numbers ...' warning, use the relevant IntelliJ Inspection ...
Place your cursor over 'com.android.support:appcompat-v7:21.0.+' (anywhere in the colored section of the warning).
Alt + Enter > "Replace with specific version".
There are plans to include the latest specific version number in the warning. See Issue 78737: Have the "Avoid using + in version numbers" gradle library warning suggest the version currently in use.
you can get the version list of support-v4 at here: \sdk\extras\android\m2repository\com\android\support\support-v4
You can see the versions at Google's Maven Repository. Just find the item entry com.android.support and click the plus to expand it. Scroll down and click on any artifact such as support-v13 and you'll see folders named after the version number.
This will work:
apply plugin: 'com.android.application'
android {
compileSdkVersion 20
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "com.example.myApp"
minSdkVersion 19
targetSdkVersion 20
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
}
dependencies {
compile 'com.android.support:support-v4:20.0.0')
}