What's in gradle a group, module and artifact? - android

The gradle docs don't take the time to explain the entities they are dealing with. That's why I want to ask such a basic question.
I've got a to understand in detail, what the terms group, module and artifact really mean to alter this code:
compile('com.thoughtworks.xstream:xstream:1.4.7') {
exclude group: 'xmlpull', module: 'xmlpull'
}
About a year ago I used that exclude statement I took from Android dalvik conversion for xmlpullparser to fix a Multiple dex files failure.
However, after upgrading to Android Studio 3.0 that error occurrs again! Now it says: Multiple dex files define Lorg/xmlpull/mxp1/MXParser and sometimes ...XmlPullParserException.java So, id like to understand how the parameters I give exclude must be shaped.
Reading the documentation one could think a group is the package name and the artifact is the class:
//excluding a particular transitive dependency:
exclude module: 'cglib' //by artifact name
exclude group: 'org.jmock' //by group
exclude group: 'org.unwanted', module: 'iAmBuggy' //by both name and group
Another chinese page (translated) used those excludes
compile ( 'com.thoughtworks.xstream: xstream: 1.4.7' ) {
exclude group : 'xmlpull'
exclude group : 'XmlPullParser'
}
Built on that findings wonder
how xmlpull worked when the package name begins with org.xmlpull?
what projects those terms refer to in my scenario. Where was the group name defined?
What kinda group is XmlPullParser?
Must I clean, rebuild or just build the project after altering those parameters? Because sometimes it complains about different files.

The group, artifact and version are chosen semi randomly and do NOT need to match packages or classes in the jar file.
For example commons-lang has groupId = 'commons-lang' but the classes are in org.apache.commons.lang.* package
The group, artifact and version are defined within the build file of the project. In maven this will be in pom.xml in gradle this will be in build.gradle (and settings.gradle)
If you want to know the group, artifact, version for a project (aka GAV, aka maven co-ordinates) you will usually go to the project's home page.
You can also use the maven central advanced search to "fuzzy" search eg by artifactId or by a classname within a jar. If you are using an in-house repository you can likely "fuzzy" search via the web interface there also

Related

java.lang.RuntimeException: Duplicate class com.google.protobuf.AbstractMessageLite when adding firebase remote config

When I am adding com.google.firebase:firebase-config:19.1.0 to use firebase remote config having this issue.
java.lang.RuntimeException: Duplicate class com.google.protobuf.AbstractMessageLite found in modules protobuf-java-2.5.0.jar (com.google.protobuf:protobuf-java:2.5.0) and protobuf-lite-3.0.1.jar (com.google.protobuf:protobuf-lite:3.0.1)
I have updated both firebase-analytics and google-play-services to latest version. But still the problem exist.
But when I changed remote config to older version 18.0.0 or less then its working fine. But I want to use the latest version.
My dependencies:
firebase_analytics : "com.google.firebase:firebase-analytics:17.2.2",
fcm : "com.google.firebase:firebase-messaging:20.1.0",
performance : "com.google.firebase:firebase-perf:19.0.0",
config : "com.google.firebase:firebase-config:19.0.0",
Also tried to exclude below doesn't work:
exclude group: 'com.google.protobuf', module: 'protobuf-lite'
exclude group: 'com.google.protobuf', module: 'protobuf-java'
Finally, I fixed this issue. First lets understand the issue:
protobuf-java and protobuf-lite are incompatible packages. They both include classes in the com.google.protobuf package. protobuf-java is typically used in packages intended for desktop and server-side use (i.e. regular Java), while protobuf-lite is frequently used in packages that target Android.
Firebase packages depend upon protobuf-lite. Something else in your project must depend on protobuf-java. You can see a tree view of your dependencies by following these instructions: https://stackoverflow.com/a/35235229.
The exclusion is required to resolve the incompatibility, though really you should see if there's an android-specific variant of whatever package you're using that's introducing protobuf-java.
To exclude the duplicate classes that's causing the problem, add the following code into your build.gradle (app module) file:
android {
...
configurations {
implementation.exclude module:'protobuf-lite'
}
}
try this, add the code in app's build
configurations {
implementation.exclude module:'protobuf-java'
}
The missing classes is a known issue. Full proto and lite proto can't be mixed; they use different generated code. Do not depend on protobuf-java as an implementation dependency, but as a protobuf dependency which will cause gradle-protobuf-plugin to generate code for the .protos.
dependencies {
...
protobuf 'com.google.protobuf:protobuf-java:3.7.1'
}
Note that this solution only really works for an application. If you are a library, it is dangerous because users of your library may then see multiple copied of the generated code for the well-known protos.

Program type already present androidx.exifinterface.R

I recently added implementation 'com.google.android.play:core:1.6.4' as a dependency in my android project and now Intellij is complaining that Program type already present: androidx.exifinterface.R. What does this mean and how do I fix this?
Note: this is meant to be a Q&A question. I've already found a solution and I want to share with others.
I recently ran into an issue where android studio would complain that Program type already present: androidx.exifinterface.R. This happened after adding the implementation 'com.google.android.play:core:1.6.4' dependency. I had stumbled on this before with androidx.asynclayoutinflater.R. I've found the that adding something like the following to your module level gradle file will fix it:
configurations.all {
// This is from a previous, similar issue
exclude group: "androidx.asynclayoutinflater", module: "asynclayoutinflater"
// This is the LOC that fixed the issue in this post
exclude group: "androidx.exifinterface", module: "exifinterface"
}
The pattern seems to be:
if there's a complaint about androidx.MODULE_X.R already being present
then add
exclude group: "androidx.MODULE_X", module: "MODULE_X"
to configurations.all in module level gradle file
This worked for both asynclayoutinflater and now exifinterface. I don't know if the pattern scales but so far it has worked. My understanding of the underlying issue is that two dependencies in the module dependency graph (eg com.google.android.play:core) explicitly include the problematic module (eg exifinterface) and so we need to exlude one of those explicit dependencies. My understanding might be wrong.

How to know if duplicate library is Module or group?

I am getting duplicate library error on Gradle, One of the aar file i have added in my project has come up with the http-client-library library.
Now i need to remove this library from this SDK library file, because some other library is also using it.
I have tried following.
compile(name: 'SDK-app-1.0.0', ext: 'aar'){
exclude module: 'httpclient'
}
but it does not effect it, I can still see httpclient library in the sub module of SDK-app library.
I am unable to understand what should i need to add here? Is it a Module or library, or should i set transitive=true to remove this library from the aar file.
and When i try to add this library in my project
Duplicate zip entry
[android-async-http-1.4.9.jar:com/loopj/android/http/AsyncHttpClient$1.class])
If you know the compile statement
The easiest way of figuring this thing out is getting the compile statement you would usually add the dependency to your project.
Then you can take it apart to get the group and the module. Like so:
Identify first colon
Identify second colon
Everything from the beginning to the first colon is group
Everything between first and second colon is module
Excluding the dependency would be as easy as:
compile 'some.imaginary:library:4.8.15', {
exclude group: 'com.google.dagger', module: 'dagger'
}
If you don't know the compile statement
Things get a bit more complicated (but not much) if you don't have your compile statement. You can either:
Try to figure out the module and the group looking for the artifact online. For example in the Maven repository search engine. If you look at the Maven dependency you can see the groupId tag which represents your group and the artifactId tag which represents your module.
Or you can use gradle locally:
Open Terminal pane in your Android Studio:
Type in: ./gradlew androidDependencies
Find the row that relates to the library you're trying to exclude and split it the same way I did in the first example:

Android Studio: Duplicate files copied in APK META-INF/DEPENDENCIES when compile

I exported my project from Eclipse and imported to Android Studio using the instructions in this link: http://developer.android.com/sdk/installing/migrate.html
When I build, I have an error:
Duplicate files copied in APK META-INF/DEPENDENCIES
After searching, I found a solution: add
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
}
into build.gradle. And it works!
But I don't understand why I had this error and why I've had to apply that fix. Can anybody explain?
While Scott Barta's answer is correct, is lacks a simple and common solution: just add
android {
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
}
to your build.gradle to ignore those duplicates.
In Android Gradle builds, you're not permitted to include the same file with the same path more than once in the output. In your build, there were two META-INF/DEPENDENCIES files coming from different places. Since you don't need this file at all in your application, the simplest thing to do is to tell the build system to ignore it altogether, which is what this exclude directive does.
There's also a pickFirst directive to tell the build system to keep one of the copies; there's a tiny amount of detail on that in Android Gradle plugin 0.7.0: "duplicate files during packaging of APK".
Android builds in Gradle are rather strict about duplicate files, which can make life difficult. There's a similar problem if you include the same Java class more than once, where you get the "Multiple dex files define" error (see Multiple dex files define Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCompat) for a typical example).
Other build systems are more lenient. It's typical in Java that if you include the same class more than once in a classpath, for example, the first copy it sees is the one that's used; duplicates after that are ignored. This is in most cases easier to deal with, but it has a couple problems. The biggest one is that there can be subtle errors if multiple different versions of a file creep into the build without you knowing -- it can be difficult to figure out what's going on. When you do figure it out, you can usually solve it by juggling the order in which things are included to make sure the one you want makes it to the final output, but in very complex builds, this can be difficult to achieve, and it can happen that doing seemingly unrelated things like including new libraries in your project can upset the ordering and lead to a lot of woe.
For that reason, Gradle has the philosophy of not relying on ordering of things to determine "winners" in the game of resolving duplicates, and it forces the developer to make all dependencies explicit. Android's implementation of its build system on top of Gradle follows that philosophy.
The simplest solution is to add
packagingOptions {
pickFirst 'META-INF/*'
}
to your build.gradle in android section
The easiest way I've found to resolve this problem is to use a wildcard, so you don't find yourself having to manually declare each file in conflict.
packagingOptions {
pickFirst '**'
}
In case that anyone having these problem while uploading new .apk to Google Play Store, after updatng Android Studio ;
click V1 Jar Signature not Full Apk Signature while Generating new Apk with old Keystore
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.google.android.gms:play-services-ads:10.2.1'
implementation 'com.android.support:support-annotations:25.0.1'
testImplementation 'junit:junit:4.12'
**// select only one in two line below** implementation ‘package’ //implementation project(‘:package’)
}
// good luck

Gradle dependencies for Android app which uses google cloud endpoint client libs

While following along with the demo in this video :
https://www.youtube.com/watch?v=7Sp4Lr3Qmcw
I noticed that at 16:56 in the video :
http://youtu.be/7Sp4Lr3Qmcw?t=16m56s
the presenter pastes the following snippet into build.gradle of the android app :
compile('com.google.todotxt.backend:taskApi:v1-1.17.0-rc-SNAPSHOT') {
exclude(group: 'org.apache.httpcomponents', module: 'httpclient')
}
compile('com.google.http-client:google-http-client-android:1.17.0-rc') {
exclude(group: 'com.google.android', module: 'android')
exclude(group: 'org.apache.httpcomponents', module: 'httpclient')
}
but does not explain how he got those lines.
The previous step of :
==> ./gradlew appengineEndpointsInstallClientLibs
also does not show what artifacts were created and what the names of the artifacts were.
So, it is not clear how the presenter obtained the names of the artifacts from the previous step.
Does anyone know how the presenter was able to figure out what the names are, of the artifacts generated from the the install-client-libraries-step are.
That video is from an older version of Android Studio. Updated instructions for integrating an appengine backend with your android application are available at : https://github.com/GoogleCloudPlatform/gradle-appengine-templates
Basically there is some cross module dependency configuration that tells your android module to pull the endpoints artifact from the appengine module. The new flow doesn't use a Maven repository anymore.
However if you still want to find out how the names are discovered. You have to go into the build directory of your appengine project, into the client libraries folder, unzip those zips and looks in the build.gradle file for the client library to see the artifact output name.

Categories

Resources