user3572586
user3572586

Reputation:

How to create an Android library from the code that have gradle dependency?

I am creating an Android library having dependencies based on the following components.

  1. My library code
  2. layout and resources file
  3. Gradle dependencies to third parties.

First I think of creating .jar file for my library but then I figured out that laulyoit and resources files are not compiled with the jar. Then i decided to create AAR file. Please suggest if this one is right move or is there any other alternative?

Now the main problem I am stuck with gradle dependencies. We are creating a paid library that uses some third parties like google only available through Gradle. Now since I am creating an AAR file, there would be no Manifest.xml and Gradle file, how can I integrate the third parties with my own code. And We have the strict instructions that we must not tell the users of library to include that third parties to include. In simple words, we cannot let the users know what kind of third parties our library is using. So is there any way I can create an AAR file that also have the gradle dependencies pre-compiled with this without revealing the user what services we are using?

Update 1

Here is my build.gradle for Library

apply plugin: 'com.android.library'

android {
   compileSdkVersion 25
   buildToolsVersion "25.0.2"
   defaultConfig {
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
        testInstrumentationRunner         "android.support.test.runner.AndroidJUnitRunner"
}
   dexOptions {
        preDexLibraries = false
        javaMaxHeapSize "4g" // 2g should be also OK
   }
   buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
 }

 dependencies {
 compile fileTree(dir: 'libs', include: ['*.jar'])
 androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
  })
   compile 'com.android.support:appcompat-v7:+'

   compile 'com.google.android.gms:play-services-vision:10.2.1'

   testCompile 'junit:junit:4.12'
}

After the I am moving my .aar file to local maven and creating then using the output file in my application Project. Here is the gradle for same.

apply plugin: 'com.android.application'
android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
    applicationId "com.jarvis.myapplication"
    minSdkVersion 15
    targetSdkVersion 25
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
    buildTypes {
        release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
    })

    compile('com.company:mylibrary:1.0@aar')
        {
            transitive = true
        }
    compile 'com.android.support:appcompat-v7:25.3.0'
    testCompile 'junit:junit:4.12'
}

Upvotes: 13

Views: 1502

Answers (4)

Fco P.
Fco P.

Reputation: 2701

First: AAR files have manifests. And, if you use gradle to build them, they'll have gradle build scripts.

So, the first part of your problem is moot. Just create an AAR library and add the dependencies using the gradle-maven plugin (gradle) or the maven-android plugin (maven).

For the second part, is a bit more tricky. What you want is essentially a shaded AAR or Uber-AAR, an AAR file which brings the dependencies bundled into itself. You can achieve that by using the maven-shade plugin or the gradle-shade plugin (depending on which system do you use to create the aar). With that approach, your clients can have a serious problem. You see, in java, your project works with the concept of dependency scopes and classpath. Scopes means the moment in time when the dependency is needed and who brings it. Classpath is the whole collection of classes used by a project, both the ones from dependencies or the ones from the project itself (so a client will always be able to know what are you using, because the compiler also needs to know). Therefore, you can't have several versions of a dependency in the path, because the classes would clash, rendering the project impossible to compile. That's why we usually don't attempt to hide which dependencies we are using; it allows easier resolution of conflicts. If you use a popular dependency (like google maps) you risk your library becoming a problem for your clients and therefore, being discarded. It would be best for you to develop the library with the designed contracts, then, a secondary plugin with a particular implementation using certain dependencies. That way you'll project would be easier to maintain and not tied to the dependencies. In that case, if the worst happens and your implementation's dependencies are incompatible with your client's projects, it will be easier to create a secondary implementation without compromising your code.

Link to the maven shade plugin: https://maven.apache.org/plugins/maven-shade-plugin/

Link to the gradle shade plugin: https://github.com/zawn/android-shade-plugin

Upvotes: 2

Magesh Pandian
Magesh Pandian

Reputation: 9389

Hi @user3572586,

  • The aar file doesn't contain the transitive dependencies and doesn't have a pom file which describes the dependencies used by the library.

  • It means that, if you are importing a aar file using a flatDir repo you have to specify the dependencies also in your project.

  • You should use a maven repository (you have to publish the library in a private or public maven repo), you will not have the same issue.

  • In this case, gradle downloads the dependencies using the pom file which will contains the dependencies list.

To hide paid lib from user better create package for individual library inside your project then generate .aar file. Myself i create one live stream lib same issue face on that time dependencies module's are move to inside my project then make .aar file.

Upvotes: 3

Sreehari
Sreehari

Reputation: 5655

You can create an *.aar file with all required dependencies in your Library project.

Now add this *.aar file either manually or as a dependency module to the targeted project. Once the main project is combined, this will give merged Android Manifest file.

The following structure is having Library project (libraryModule) added as a dependency to main project. Again the libraryModule is having internal dependency for internallib

MainProject ===> libraryModule ===> internallib

enter image description here

As per your comment, the multidex issue can be resolved by adding the following in build.gradle (Module: app)

defaultConfig {

 .....
 multiDexEnabled true
 .....
}

Upvotes: 2

Grisgram
Grisgram

Reputation: 3253

If you create an .aar project there is a manifest file and it will get merged with the apps' manifest upon compile. That all works fine. You can use any gradle dependency in the .aar project, even proguard obfuscation and signing.

To compile an .aar library in the main app, put it like this in your dependencies of your build.grade file:

dependencies {
    compile(name:'your_lib_name', ext:'aar')
}

You have to copy the .aar file to the libs folder in your app folder.

But one thing is clear: If someone uses your .aar file, he or she can look at the merged manifest file in android studio any time and you can not hide your dependencies. At least, as far as I know. Android is driven strongly by open source libraries (even through maven) and in most cases you even have to include the licenses of your used external libraries, visible to the user as menu item or link in your app. Otherwise you violate licenses and maybe even Terms of Use in some cases. You may not hide them.

Upvotes: 7

Related Questions