Android Library(Kotlin) Creation, Access, Deploy, Problems & Fixes Everything You Want to Know (Part 1).

Arul mani
The Startup
Published in
7 min readAug 16, 2020

Every Android developer knows how time taking is to create a new project from the scratch so rectify this android development have special architecture called modules architecture. We can reduce time, reuse the code by configuring into your project here is an elaborated guide to a modular architecture.

Photo by Ashkan Forouzani on Unsplash

Creating a module is pretty simple thanks to the android studio by following steps its do work for you.

To add a new module to your project for a new device, proceed as follows:

  1. Click File > New > New Module.
  2. In the Create New Module window that appears, Android Studio offers the following device modules:
  • Phone & Tablet Module
  • Wear OS Module
  • Android TV Module
  • Glass Module
  1. Select the module for the device you want, and then click Next.
  2. In the Configure your new module form, enter the following details:
  • Application Name: This name is used as the title of your app launcher icon for the new module.
  • Module Name: This text is used as the name of the folder where your source code and resources files are visible.
  • Package Name: This is the Java namespace for the code in your module. It is added as the package attribute in the module's Android manifest file.
  • Minimum SDK: This setting indicates the lowest version of the Android platform that the app module supports. This value sets the minSdkVersion attribute in the build.gradle file, which you can edit later.
  1. Then click Next.
  2. In the Create New Module window that appears, Android Studio offers the following device modules:

Select the Phone & Tablet Module and then click Next.

  1. Click an activity template with which you want to start, and then click Next. If you don’t need an activity, click Add No Activity, click Finish, and then you’re done.
  2. If you chose an activity template, enter the settings for your activity on the Customize the Activity page. Most templates ask for an Activity Name, Layout Name, Title, and Source Language, but each template has activity-specific settings. Click Finish. When you create an app module with an activity template, you can immediately run and test the module on your device.

Android Studio creates all the necessary files for the new module and syncs the project with the new module gradle files. Adding a module for a new device also adds any required dependencies for the target device to the module’s build file.

REF : https://developer.android.com/studio/projects/add-app-module

Modular Architechture Usage

Let's talk about the usage of modular architecture. Follow below link to use modular architecture in order to WHERE/WHY you want to choose this approach.

I hope the above details explain about modular and let's see how to consume by the in-app module.

Photo by Randy ORourke on Unsplash

APP -> Modular Communication

The first point is how to access the modules from your app we can use builder class to configure and get access from the App module.

APP -> Modular Communication

In Modular define this class

class LibOptions(val title: String, val body: String /*..more fields */) {

class Builder {

private lateinit var title: String
private lateinit var body: String
//... more fields

fun setTitle(title: String): Builder {
this.title = title
return this;
}

fun setBody(body: String): Builder {
this.body = body;
return this;
}

fun create(): LibOptions {
return LibOptions(title, body)
}
}
}

The above class is a simple builder class that contains details that we want to sent to Modular.

Next, Declare Singleton INSTANCE of Library to get access from the app.

For singleton instance creation we can use by following pattern.

open class SingletonHolder<out T: Any, in A>(creator: (A) -> T) {
private var creator: ((A) -> T)? = creator
@Volatile private var instance: T? = null

fun getInstance(arg: A): T {
val i = instance
if (i != null) {
return i
}

return synchronized(this) {
val i2 = instance
if (i2 != null) {
i2
} else {
val created = creator!!(arg)
instance = created
creator = null
created
}
}
}
}

Want to know more about singleton instance follow below link.

Let's create Instance LibManger,

import android.content.Context
import androidx.appcompat.app.AlertDialog

class LibManager constructor(val context: Context) {

init {
// do some stuff
}

fun show(options: LibOptions) {
val builder = AlertDialog.Builder(context)
builder.setTitle(options.body).setMessage(options.body)
builder.setNegativeButton("Close") { dialog, which -> dialog?.dismiss() }
options.body
}

companion object : SingletonHolder<LibManager, Context>(::LibManager)
}

Now we can call this method in the App Module using this singleton class.

LibManager.getInstance(this).show(LibOptions.Builder().setBody("Alert Dialog BODY").setTitle("Alert").create())

When we create an android module in an android studio it automatically add the below section in App.Gradle

implementation project(":library")

We can easily reuse this module library in every project by using

File -> New -> Import Module

But the problem is the whole module source code must be in the same system to use in mutiple project. For that we can Deploy library to maven, jCenter repository then we can consume it.

For example, In App.Gradle

implementation 'com.domain.library:alert-library:1.0.0'

Deploy & Release

An Android library is structurally the same as an Android app module. It can include everything needed to build an app, including source code, resource files, and an Android manifest. However, instead of compiling into an APK that runs on a device, an Android library compiles into an Android Archive (AAR) file that you can use as a dependency for an Android app module. Unlike JAR files, AAR files can contain Android resources and a manifest file, which allows you to bundle in shared resources like layouts and drawables in addition to Java classes and methods.

Photo by Vidar Nordli-Mathisen on Unsplash

There are plenty of platforms for hosting your Android library and create its Gradle or maven dependency. You can choose over JitPack or JCenter or Maven Central.

Ref: Follow this link to configure the publication.

JCenter

It's quite a time to set up configurations mostly preferable for organization because source code kept in private.

JitPack

One of the easiest way to publish no need to create an account and not a lot of configurations.

Problems & Fixs

The above example didn’t use any external library in the library module. For example if we add some library like stylable toast in library when publish happens its also need to ship with package.

Simply,

LibraryA is consumed LibraryB when I use LibraryA in App its doesn't know about LibraryB so it will cause runtime exception(No Class Found Exception).

This is also known as Transitive Dependency

Transitive Dependency

A variant of a component can have dependencies on other modules to work properly, so-called transitive dependencies. Releases of a module hosted on a repository can provide metadata to declare those transitive dependencies. By default, Gradle resolves transitive dependencies automatically. The version selection for transitive dependencies can be influenced by declaring dependency constraints.

To solve this we need to add the “pom” file which contains all dependency details.

A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details used by Maven to build the project. It contains default values for most projects.

First, We need to import the external library in Gradle by using api or implementation.

For example, In Module.Gradle

dependencies {
//...
api 'com.muddzdev:styleabletoast:2.2.3' // retrofit
api 'com.google.code.gson:gson:2.8.6'
api 'com.squareup.retrofit2:retrofit:2.6.1'
api 'com.squareup.retrofit2:converter-gson:2.6.1'

//...
}

Then add this line end of Module.Gradle

publishing {
publications {
aar(MavenPublication) {
groupId packageName
version = libraryVersion
artifactId project.getName()

// Tell maven to prepare the generated "*.aar" file for publishing
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")

pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
// Iterate over the api dependencies (we don't want the test ones), adding a <dependency> node for each
configurations.api.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
}
}

That's it, there is no need to generate pom file on own above code automatically get “api’ and add it to pom file.

That's all for PART 1.

Let's see in PART 2.

Reference:

--

--