Android Studio Gradle Cannot resolve symbol 'applicationVariants' - android

I'm trying to get around an annoying issue with Gradle that does not allow libraries to have different min/target sdk's. The solution was to add the following to build.gradle.
android.applicationVariants.all{ variant ->
// This is an annoying hack to get around the fact that the Gradle plugin does not support
// having libraries with different minSdkVersions. Play Services has a min version of 9 (Gingerbread)
// but Android Maps Utils supports 8 (Froyo) still
variant.processManifest.doFirst {
File manifestFile = file("${buildDir}/exploded-bundles/ComGoogleMapsAndroidAndroidMapsUtils03.aar/AndroidManifest.xml")
if (manifestFile.exists()) {
println("Replacing minSdkVersion in Android Maps Utils")
String content = manifestFile.getText('UTF-8')
content = content.replaceAll(/minSdkVersion="8"/, 'minSdkVersion=\"9\"')
manifestFile.write(content, 'UTF-8')
println(content)
}
}
}
However when i do that, I get an error that applicationVariants cannot be resolved. How do I fix this?

Aparrently, this is an Android Studio bug and is telling me there are errors where there's none. Building and ignoring works fine.

Related

NoClassDefFoundError on running unit test after updating Android Studio to ArticFox | 2020.3.1

Test Events were not Received Error:
NoClassDefFoundError on running unit test after updating android studio to ArticFox | 2020.3.1.
Below is the full error:
java.lang.NoClassDefFoundError: jdk/internal/reflect/GeneratedSerializationConstructorAccessor1
at jdk.internal.reflect.GeneratedSerializationConstructorAccessor1.newInstance(Unknown Source)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at java.base/java.io.ObjectStreamClass.newInstance(ObjectStreamClass.java:1092)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2180)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1679)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:493)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:451)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:122)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:68)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:73)
Caused by: java.lang.ClassNotFoundException: jdk.internal.reflect.GeneratedSerializationConstructorAccessor1
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:471)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 11 more
I have just downloaded the latest android studio, clone a project and trying to run unit tests.
How can I fix this? I am using embedded JDK (which is Java 11.0).
It was happening due to the jacoco. Latest android studio comes with Java 11 but we were using Java 9. Making below changes fixed it.
jacoco { includeNoLocationClasses = true }
to
jacoco {
includeNoLocationClasses = true
excludes = ['jdk.internal.*']
}
Android Studio now using JDK 11. So, if you are using a lower version of JDK and JaCoCo, it can be a solution:
You need to add the following line to the JaCoCo block(s) in your build.gradle file:
excludes = ['jdk.internal.*']
So, the final blocks look likes this:
jacoco {
includeNoLocationClasses = true
excludes = ['jdk.internal.*']
}
You can find the reason in release note:
When running in Android Studio, the Gradle build tool uses Studio's bundled JDK. In previous releases, JDK 8 was bundled with Studio. In 4.2, however, JDK 11 is now bundled instead. When using the new bundled JDK to run Gradle, this may result in some incompatibility or impact JVM performance due to changes to the garbage collector. These issues are described in the AGP release notes.
For anyone looking how it is done in Kotlin:
tasks.withType<Test> {
extensions.configure(JacocoTaskExtension::class) {
isIncludeNoLocationClasses = true
excludes = listOf("jdk.internal.*")
}
}

Javadoc is not being generated for Android project

I'm working on an Android project and trying to generate javadoc with the task below, but it doesn't generate anything.
I have tried to trace back the issue to changes in the project. Checking out past commits and trying to create javadoc fails, even though in the past it worked.
The only thing for sure that changed for me that might explain this behaviour is the upgrade to a newer version of macOs Big Sur and updating Android Studio.
Does anyone have an idea what the problem might be?
Setup:
macOS Big Sur Version 11.4
Android Studio 4.2.1
Gradle 6.5
task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) {
if (JavaVersion.current().isJava8Compatible()) {
options.addStringOption('Xdoclint:none', '-quiet')
}
options.memberLevel = JavadocMemberLevel.PUBLIC
failOnError = false
source = variant.javaCompiler.source
def androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar"
doFirst {
classpath = files(variant.javaCompile.classpath.files) + files(androidJar)
}
options {
links "http://docs.oracle.com/javase/7/docs/api/"
linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference"
}
}
Well after a long time of searching I found the answer: it was the update from AS 4.1.3 to 4.2.x with which Google decided to package Java11 instead of 8.
Building and compiling was possible, but javadoc generation was broken for whatever reason.

Android + coreLibraryDesugaring: which Java 11 APIs can I expect to work?

I'm trying to migrate some Java library from 'normal' JVM to android and stuck with some Java11 APIs used in the code.
The first thing I already got - Java11 language features seems to work only with Canary build of Android Studio, see answer here
Now I need to get understanding about which APIs can be really used. Here are two use-cases which do not work for me and I can't get if I'm doing something wrong or it never should work:
List.copyOf() - introduced in Java11, method copyOf is not available on android. Methods 'List.of()', introduced with Java 9, work OK.
class java.lang.invoke.LambdaMetafactory - introduced with Java 1.8 - to be used for programmatic creation of lambdas for usage instead for reflection, is not visible on Android.
I see both of them in sources of desugar_jdk_libs here:
https://github.com/google/desugar_jdk_libs/blob/master/jdk11/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java
https://github.com/google/desugar_jdk_libs/blob/master/src/share/classes/java/util/List.java
So - the question is: how can I identify if some Java API is supposed to be available in 'desugared' android build or no? What really can be expected from 'desugaring'?
Steps to reproduce:
Using Android Studio Canary generate a dummy "Basic Activity" project
Make sure following is provided in build.gradle
android {
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}
Add following lines somewhere in code
List<Integer> ints1 = List.of(1, 2, 3);
Supplier<List<Object>> listSupplier = () -> new ArrayList<>();
List<Object> alist = listSupplier.get();
List<Integer> ints2 = List.copyOf(ints1);
LambdaMetafactory.metafactory(null,null,null,null,null,null);
Last 2 lines fail to compile for me.
PS: final application is supposed to work on Android 10+.
Contrary to the other answer, desugaring is totally possible.
The dependency to add is
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}
You can find more information at the official Android Java 8 desugaring documentation.
Desugaring lib is considered unofficial. We can't expect an exact answer. We get the feature when it is ready. Now List.copyOf() method now working with the latest Gradle version.
About the LambdaMetafactory class, It is not included in Android Javadoc. This means we assume we don't have LambdaMetafactory at all. Google stripped down some java API for being lightweight.
In general, We should check android Javadoc first. If android Javadoc has no mention about some API. We can be sure we won't get that feature anytime soon.

Gradle code broken after updating to gradle 6.x variant.getVariantData().getVariantConfiguration() not working

I defined manifest placeholders for different variants using following code.
android.applicationVariants.all { variant ->
// def names = variant.getVariantData().getVariantConfiguration().getFlavorName()
def mergedFlv = variant.getVariantData().getVariantConfiguration().getMergedFlavor()
mergedFlv.manifestPlaceholders = [pl1: mergedFlv.getApplicationId() + mergedFlv.getApplicationIdSuffix()]
It was working well. But I updated to the latest version of Android Studio a week ago and also updated gradle version for this project when Android Studio prompted and the Android Studio throws following error.
No signature of method: com.android.build.gradle.internal.variant.ApplicationVariantData.getVariantConfiguration() is applicable for argument types: () values: []
How do I fix this?
Update
I found this class at https://android.googlesource.com/platform/tools/build/+/0d498ccf6f91a12c036b382b7ae2b1a809eb2b9d/gradle/src/main/groovy/com/android/build/gradle/internal/variant/ApplicationVariantData.java
It does not have getVariantConfiguration() method. But it is extending ApkVariantData class which in turn is extending BaseVariantData. BaseVariantData has this public method getVariantConfiguration()
Thus it should be accessible. I closed and reopened project as well as android studio and tried building project again too... Doesn't seem to work.
Any help please
As of now I downgraded my Android Gradle Plugin Version from 4.0.0 to 3.6.3 and Gradle Version from 6.5.1 to 5.6.4 following this answer (method to downgrade) and it worked.
There seems to be problem/bug with Gradle.
Refer this post.
I think this may no longer work. See Android 4.0 Known Issues - Variant Output
Try this instead:
android.applicationVariants.all { variant ->
// def names = variant.getFlavorName()
def mergedFlv = variant.getMergedFlavor()
mergedFlv.manifestPlaceholders = [pl1: mergedFlv.getApplicationId() + mergedFlv.getApplicationIdSuffix()]
It worked for me.

Getting the Android SDK directory within a gradle task

Recently the gradle plugin for android got updated (with android studio), after which the previous way of getting to the SDK directory ceased to work. The expression
${android.plugin.sdkDirectory}
which worked in an older version now returns the error
Error:(42, 0) No such property: sdkDirectory for class: com.android.build.gradle.LibraryPlugin
What would be the proper way of getting the android SDK directory being used, preferably independent of the user's configuration such as plugin and gradle version? The script needs to be shareable with several users.
Since all the previous answers depend on the environment or specific user intervention on top of normal configuration, I'll just post my technically messy fix.
if (android.hasProperty('plugin')) {
if (android.plugin.hasProperty('sdkHandler')) {
androidPath = android.plugin.sdkHandler.sdkFolder
} else {
androidPath = android.plugin.sdkDirectory
}
} else {
androidPath = android.sdkDirectory
}
Unlike all previous methods, this actually works, but it still looks hacky.
In gradle.properties set location sdkdir=/home/user/android-sdk and then in gradle you can use $sdkdir
I'm using Android gradle plugin v1.2.3 and this works fine:
${android.sdkDirectory}
You can use
$System.env.ANDROID_HOME
export ANDROID_HOME=/xxx/xxx/ in shell, then use it by System.env.ANDROID_HOME in gradle file.

Categories

Resources