Search code examples
javaandroidgradleshared-librariesdex

Android Studio dynamically loaded library


I have an Android application that dynamically loads a library using DexClassLoader. Until now the application and the library were developed in separate projects. I would like to unite the projects into a single project (two modules in a project?) but I am not sure how to achieve it with Android Studio/Gradle. Note, that I don't want to add a static dependency between the app and the library. The result I want to achieve is:

  1. Both the application and the library are in the same project.
  2. The building of the app and the library may be in two separate steps (but one step could be nice :D ).
  3. The compiled library must be eventually an asset of the application and be bundled in the resulting APK; i.e., not statically compiled into the application but be a stand-alone file in the APK.

Any ideas?


Solution

  • Xiaomi's answer gave a good direction, but the eventual solution was somewhat different.

    Solution overview

    The project is going to contain two modules: one for the application and one for the library. The app module will depend on the library so the library will be built before the app. When the JAR file is ready, it will be converted into DEX and copied into the app's assets library. The build activity of the application will automatically bundle the assets folder in the final APK.

    Step-by-step solution

    1. If it isn't already there, include the library module in the project settings file settings.gradle:

      include ':app', ':libmynewlibrary'
      
    2. Add the dependency in the build.gradle of app module:

      dependencies {
          ...
          compile project(':libmynewlibrary')
      }
      
    3. Now the tricky part. We want to add a custom action immediately after the JAR is created. Luckily Android Gradle plugin has a predefined task "jar" - it builds the JAR obviously. We will just add something to it in the lib's build.gradle. Notice that the task is implicit and isn't in the gradle file at all. We are just expanding it by adding doLast to it:

      jar {
          doLast {
              exec {
                  executable "dx"
                  args "--verbose", "--dex", "--output=../app/src/main/assets/mynewlib.dex", "build/libs/libmynewlib.jar"
              }
          }
      }