My goal is to distribute an .aar file that can be used by other developers in their projects. The problem I find is when I try integrate my .aar into other project, is I need specify all of the dependencies in their build.gradle file that I have already included in my .aar build.gradle.
My question is if it's possible to only include my library as a dependency and somehow the libraries that my library depends on will get included in the other project.
If you distribute your AAR through an artifact repository, you can also distribute dependency information. In the case of a Maven-style repository — the most popular kind nowadays — that dependency information is part of the POM file that would be published with the AAR. You can use established repositories (e.g., JCenter, Maven Central) or roll your own (as Google did with maven.google.com and what I do on Amazon S3 with repo.commonsware.com).
If, instead, you insist upon distributing the AAR as a plain file, then you have no means of distributing dependency information, other than via documentation. This is no different than distributing JARs.
Related
I am creating SDK and want to modularize it.
And prevent internal APIs from being exposed on your public interface.
Want optional dependency based on features required. If features is not required we can remove dependency and code and imports should not work.
Tried Ways
Submodule dependencies
Fat AAR
Submodule dependencies
when a library module gets built, the .aar artifact will only include code and resources that are in the library module itself. It won’t include:
any code or resources from database and ui-components
links to its transitive dependencies (these go into the build.gradle)
So when the app module directly includes the library as a gradle dependency, it would crash due to missing classes from database and ui-components on its classpath.
Fat AAR
In the fat .aar solution, code and resources of the submodules are bundled into the main SDK module, hence creating a fat .aar
the fat .aar plugin breaks on almost every minor Android Gradle plugin update! This is because it hooks itself into particular tasks of the Android Gradle plugin and these very often get renamed/moved. However, the project maintainer need to do job at fixing those within a few weeks after the breaking change.
Also, because of the way fat .aar references dependencies from submodules, it can significantly increase the binary size of your SDK.
Is there any other possible solution?
I have a multi module android project and currently anyone in our team can access the the modules from our private maven repository.
We are using jFrog Artifactory hosted in aws for managing the repositories. The structure of our project is something like this
app
-lib1
-lib2
-lib2a
-lib2b
I want to know if there is a way by which lib2a and lib2b is not accessible as separate modules but only accessible when someone adds the dependency of the parent module in their project which is lib2 in this case
I want to know if there is a way by which lib2a and lib2b is not accessible as separate modules but only accessible when someone adds the dependency of the parent module in their project which is lib2 in this case
Short answer:
No, you can't do it.
Long answer:
When you put an artifact in a maven repo you have the artifact files (may be an aar for your android libraries) and a pom file.
The pom file describes also the transitive dependencies of the artifact.
Currently you can't specify a parent dependency or a specific maven repo to be used (this one is under development).
It means that a build system, for example gradle, read the dependency, download from the repos the pom file and download all transitive dependencies.
When you download a transitive dependency there is no way to specify if you have just downloaded the parent or if you are directly downloading it.
It can be available, or not available without conditions.
After migrating to Android plugin for Gradle 3.0 the OSS license plugin (https://developers.google.com/android/guides/opensource) no longer includes the licenses from the project's library modules dependencies. Only the "app" module.
I'm using com.google.gms:oss-licenses:0.9.1 and com.google.android.gms:play-services-oss-licenses:11.8.0
If I 'apply' the plugin to all my modules, the third_party_license data is generated in the raw folder for each module. But in the end only the data from the app module end up in the APK.
Is there any workaround for this problem?
Yes that is correct.
Based on my search on how the plugin works, the plugin would generate the data into the res/raw folder of the artifact (aar or apk, but not jar files) based on POM files it can get from the libraries. Then the rest of merging is done by Gradle Android Plugin, and not by the OSS License Plugin, which merges the res folders from all of the sources (dependency libs, modules, main app etc.). However here's is the issue, upon merging, the Android Gradle Plugin would choose one if there are duplicates of the same resource (link to explanation), and the one that is chosen is based on a priority, meaning since both the app module and the lib module are generating the R.raw.third_party_license resource which are duplicates, the one from the app module has a higher priority of being included than the one from the module hence the license information from the module are not included.
There are several ways of fixing this:
Include the same dependencies from your library module in your app module. This is probably the worst idea to do but it does not affect your app since Gradle would automatically resolve the dependencies without any issues especially if they will be of the same version, if they were of different versions then Gradle would choose the latest.
Rather than using a module dependency, publish the module to a maven repo (locally or remotely, here's a link to show how it could be done locally), and add it's dependency as such: implementation 'com.mygroup:library:1.0'. Don't forget to remove it from the project build.settings file. This would generate the POM file of the library module and hence get the plugin to read it and include it's library licenses. This means that the library should be compiled and published before compiling the app module, but also it could lead to some weird compiling issues and confusions when errors happen.
Unfortunately there is one more way that I thought would work however it didn't. It is by changing the dependencies in your library module to api instead of implementation. This would expose the library dependencies into the app module dependencies but would increase the build time of the project. But finally it didn't generate the raw resources properly because it seems that the OSS License Plugin only reads the dependencies from a POM file of library and in this case the POM file is not being generated even if the library module dependencies were exposed. Probably should post this as an enhancement or bug request to the developers of the plugin.
I have an Android module from which I export an .aar file.
I imported this .aar with Android Studio Wizard, project compiles, but crashes at runtime with "java.lang.NoClassDefFoundError".
I checked with debugger, Class.forName("retrofit2.Retrofit").. not found.
After unzipping the .aar & checking the classes.jar, I see only my packages, clearly it didn't packaged the libraries I was referencing in build.gradle (ex: Okhttp, Retrofit, Gson.. ).
What I want is a way to keep my build.gradle dependencies. I would prefer it to be packaged into the .aar if possible, else what is the option? Force the client to add in his own gradle my dependencies?
Extra info: I only have gradle dependencies, no jars.
Distribute the AAR via an artifact repository. The metadata in the artifact repository (e.g., the POM file) will contain the information about your transitive dependencies. It also will have information about the version of your AAR, so that consumers of the AARs have clear information about what version they are using. This is how nearly everything else that you are using is distributed: support libraries, Retrofit, etc.
It is possible to easily use third party libraries with gradle. For example, the following allows me to use Retrofit in my app.
dependencies {
compile 'com.squareup.retrofit:retrofit:1.9.0'
}
How does this work? Where does the library come from? In general terms, how would I go about publishing a library so that other people can import it like this?
Note: this is not a duplicate of Publish jar library to bintray using gradle/publish-jar-library-to-bintray-using-gradle. That question was asking a spefic question about one particular way to publish libraries.
Lots of this is answered in this tutorial.
How does this work?
Gradle imports the libraries from a Maven repository. The Maven repository can contain both regular .jar files and regular .aar files.
Where does the library come from?
By default, new versions of Android Studio import from JCenter. JCenter is a Maven Repository run by the company Bintray.
If you look at your Android Studio project's build.gradle, you'll see the following lines
repositories {
jcenter()
}
This tells gradle where it should look when attempting to import com.squareup.retrofit:retrofit:1.9.0.
In general terms, how would I go about publishing a library so that other people can import it like this?
You need to create a Bintray account in order to upload to JCenter since Bintray owns JCenter. Bintray's website is pretty easy to use compared to what Maven Central, the past default Maven Repository used by Android Studio.
After you've created a normal Library module inside Android Studio, you'll need to hand tweak your library module's build.gradle file in order to configure it for Maven. Finally, you use a pre-baked script to upload everything to Bintray.