AAR dependencies - bundle or not? - android

I am developing my own SDK, which in turn depends on some 3rd party SDKS. For example - OkHttp.
Should I add OkHttp to my build.gradle, or let the users of my SDK include that? In this scenario, they will probably "anyway" use it, so its safe to say they already have it.
Another point to add - not all paths of my SDK needs "OkHttp", so, in theory, some user of my SDK could use those parts only, and have not OkHttp on his APK.
Another thing I am contemplating:
If I do embed OkHttp on by build.gradle - how can users of my SDK use that OkHttp library, instead of consuming another replica?

Should I add OkHttp to my build.gradle, or let the users of my SDK include that?
Adding the dependencies in build.gradle doesn't mean packaging the dependencies inside the aar file.
The aar file doesn't contain the transitive dependencies and doesn't have a pom file which describes the dependencies used by the library.
Uploading the artifact in a maven repository you will have your aar and a pom file which will contains the dependencies list.
In this way gradle will automatically download all the dependencies tree and you can configure gradle to exclude same libraries.

Use implementation and package it - the consumer can still exclude it.
One cannot depend on something and then not package it; this won't build.
In the application package, it can/must only exists once ...so what's the point?

I will answer your questions in a reverse order
Another thing I am contemplating: If I do embed OkHttp on by build.gradle - how can users of my SDK use that OkHttp library, instead of consuming another replica?
How Gradle build system works is suppose, In my project I use your library and I'm using v2 of OkHttp and your library is using V1 of OkHttp, then the gradle will automatically use the latest version. You can read about it here
Another point to add - not all paths of my SDK needs "OkHttp", so, in theory, some user of my SDK could use those parts only, and have not OkHttp on his APK.
In my project I use your library and it uses OkHttp, whereas I don't use it in my project also, I'm not using the part of your library where you are using OkHttp but still my APK will include OKHttp in it. This can be avoided either by splitting your library into two separate libraries or me using proguard in my Project.
Should I add OkHttp to my build.gradle, or let the users of my SDK include that? In this scenario, they will probably "anyway" use it, so its safe to say they already have it.
You should not bundle it in your library you just use implementation and let the user of your library decide if he wants to exclude it or not.

You need knows about api and implementation in the gradle
The link will be helpful
Api:
Role: Declaring ,API, dependencies
Consumable? no
Resolveable? no
Description: This is where you should declare dependencies which are transitively exported to consumers, for compile.
Implemetation:
Role: Declaring, implementation, dependencies
Consumable? no
Resolveable? no
Description: This is where you should declare dependencies which are purely internal and not meant to be exposed to consumers.

Related

Error when publish to Google play and add to library to gradle

I want to publish my app to Google PLay
Error : "We found that the application uses the old version of the Google Play Developer API. From December 1, 2019, support for versions 1 and 2 of this API will cease. Update it to version 3 before this date. Read more ..."
I found, how to fix it, I need to gradle this library
implementation 'com.google.apis:google-api-services-androidpublisher:v3-rev95-1.25.0'
But when I build APK, studio show me error
<issue
id="DuplicatePlatformClasses"
severity="Fatal"
message="`httpclient` defines classes that conflict with classes now provided by Android. Solutions include finding newer versions or alternative libraries that don&apos;t have the same problem (for example, for `httpclient` use `HttpUrlConnection` or `okhttp` instead), or repackaging the library using something like `jarjar`."
category="Correctness"
priority="8"
summary="Duplicate Platform Classes"
explanation="There are a number of libraries that duplicate not just functionality of the Android platform but using the exact same class names as the ones provided in Android -- for example the apache http classes. This can lead to unexpected crashes.
To solve this, you need to either find a newer version of the library which no longer has this problem, or to repackage the library (and all of its dependencies) using something like the `jarjar` tool, or finally, rewriting the code to use different APIs (for example, for http code, consider using `HttpUrlConnection` or a library like `okhttp`).">
<location
file="D:\Applications\Radio\app\build.gradle"/>
</issue>
what am I doing wrong ?
Add this to project gradle
repositories {
mavenCentral()
}
Below code to your app gradle
dependencies {
compile 'com.google.apis:google-api-services-androidpublisher:v3-rev95-1.25.0'
}
Add this...
android {
...
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
}
}

Why compile- and run-time dependency is important?

I know the difference between the two as discussed here.
As Android developer,
Why I should care about this?
In gradle, why should I use compileOnly vs implementation/api?
Why I should care about this?
To make your apps build but not ship with unnecessary stuff.
In gradle, why should I use compileOnly vs implementation/api?
The documentation for compileOnly gives one use case as an example:
Gradle adds the dependency to the compilation classpath only (it is not added to the build output). This is useful when you're creating an Android library module and you need the dependency during compilation, but it's optional to have present at runtime. That is, if you use this configuration, then your library module must include a runtime condition to check whether the dependency is available, and then gracefully change its behavior so it can still function if it's not provided. This helps reduce the size of the final APK by not adding transient dependencies that aren't critical. This configuration behaves just like provided (which is now deprecated).
source
For example, consider a push messaging library that supports both Firebase FCM and Amazon ADM but does not require either. It would unnecessarily bloat apps if it would ship with both as transitive dependencies. With compileOnly the library can still be built. Developers using the library can select which dependencies to actually use.
Another example could be compile-time annotations that do not need to ship with the application.

How to use a Gradle dependency with local modifications?

I have an Android application using an Android library. The library is a pretty big open-source project on GitHub, and its authors publish the artifacts to Bintray. I can specify the dependency with the usual syntax dependencies { implementation 'group:artifact:version' } in the app's build.gradle.
Now I want to change some code in the library. I git clone it on my machine, I make my changes, then I build the library. But how can I tell my app to use the library I built locally, instead of the one in Bintray?
I don't want to follow the approach in Gradle Local Project Dependency, because that means that the library code is now part of the application project, but I really want to keep things separated.
I think the solution involves publishing to a local Maven repository. I followed the guide at https://proandroiddev.com/tip-work-with-third-party-projects-locally-with-gradle-961d6c9efb02 but the app's Gradle is still picking the original library from Bintray.
Bintray-based projects have the install task. That's the one to be used instead of publishToMavenLocal.
When using install, the artifact version is automatically set to X.X.X before publishing to the local repository. Therefore, in order for the app to pick up the local library, you have to edit the implementation row to group:artifact:X.X.X.
As the guide https://proandroiddev.com/tip-work-with-third-party-projects-locally-with-gradle-961d6c9efb02 suggests, you also need to add mavenLocal() as the first entry in the repositories section in the top-level build.gradle of the application.

How to get a compile error if a JAR dependency is missing?

I have an Android project with the following dependencies:
-- Android App
---> MySDK.Jar
------> 'org.apache.commons:commons-lang3:3.5'
This is MySDK.jar that has a dependency on commons-lang3.
I'm working on Android Studio and I'm thus using Gradle.
Here is my problem:
I have shared "MySDK.Jar" to someone and he has built his own Android App on top of it.
It works but we have seen that the compiler doesn't notice the missing dependency on 'org.apache.commons:commons-lang3:3.5'. At run-time there will be a crash if the code using 'org.apache.commons:commons-lang3:3.5' is called. One may not notice the problem if he doesn't call the code using this library.
I know that we can solve this issue by adding the following line to Android App build.gradle file:
compile 'org.apache.commons:commons-lang3:3.5'
I'm wondering if there is a way to get a compile error indicating such missing dependencies? It is indeed better to see the dependency problem at compilation time rather than at runtime.
What are the recommended good practices for this?
Thanks!
commons-lang3 is a transitive dependency of Android App. As such, it is often not needed for compilation - there are exceptions, especially regarding multiple levels of inheritance. So at compile time you (usually) do not know whether you miss a transitive dependency that you need at runtime.
This is where Gradle comes in. Gradle can (as Maven) resolve dependencies transitively from a Maven repository (as MavenCentral). If you put MySDK into a Maven repository (like Nexus or Artifactory, which have open source versions), everyone using MySDK will automatically draw commons-lang3 so you will not miss anything at runtime.
If you are just adding the jar file in your project you can't warning about the missing dependencies.
To do it you have to publish the jar file in a maven repo.
In this way you have a pom file which describes the dependencies that gradle has to download.
Provide a method like MySDK.init() int your MySDK.jar,call a method whe is belong to org.apache.commons:commons-lang3:3.5' in the MySDK.init() method, then put init() into onCreate() of your Application,
Another way is,putorg.apache.commons:commons-lang3:3.5 into MySDK.jar,
Hope it helps you :)

Auto import dependecies from my library

I created an android library that acts as a wrapper. I use some dependencies in the library notably Volley and Google Play Services. When I try to paste the .aar file in the project and compile it these libraries are not being imported and they throw an error. When I manually add these dependencies in the build.gradle of the new project then they work fine.
Is there way so that whenever my library is added it will auto import all the required dependencies?
just a friendly warning: including dependencies is considered a very bad practice at SHOULD BE AVOIDED.
However, if you do still want to do that, I suggest using the "download library from Maven" feature in Android Studio as described here.
This will make sure the library and all of its dependencies are downloaded.

Categories

Resources