Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Studio: using Android Modules without duplicating code

I need to implement two applications AppA and AppB that use the same Android Library LibC.

Using Android Studio, my desire is to have three projects: LibC, AppA, and AppB, with AppA and AppB referencing LibC. I cannot find a way to obtain this.

So far I have implemented AppA. While writing AppA I created a module via

File > New Module > Android Library > `LibC`

The LibC library is now in the AppA project and I need to start using it within the AppB project.

Question 1:

How do I move LibC out of project AppA and create a project only for LibC?

Question 2:

How am I supposed to create a new project containing only an Android Library?

If I start a new Android Project it keeps creating a new App.

The doc here says:

1) that I need to create a new Application and then a new module within that application (which is what I did while writing AppA);

2) that I can import existing library code into a new project.

However I do not want to copy the code of the library into the new project (which is what happens), I want to use the same files in order to keep a single code base for the library.

Is this possible? If it is, where can I find some doc about it?

like image 541
Antonio Sesto Avatar asked Feb 15 '15 16:02

Antonio Sesto


2 Answers

Since I had this requirement in my own project recently, I may have some suggestions for you.

Basically here are your options:

1. Single project with different modules

If AppA and AppB are somehow related (this is something you have to decide), you can go the easy way. You already have AppA and LibC in your project, so you only need to create another App module in Studio for AppB (File > New module > Application module)

You may see interestingly, that your project directory initially has the name AppA, and your AppA module is named app. That is because Android Studio per default names your project after the name you provided in the wizard, while your first module is always named app.

You may rename your containing project from AppA to something like project (via right-click on project > Refactor > rename, and rename the app module to AppA.

The basic structure will look like this:

Studio Project AppA (rename to "project")
|
|\_app (module AppA, rename to "AppA")
| |_ src
|
|\_AppB (module AppB)
| |_ src
|
 \_LibC (module LibC, dependency for AppA and AppB)
  |_ src

Advantage of this setting is that it is contained in one Android Studio project, and therefore you get all the Android Studio refactoring magic between your app modules and the library for free.

Imagine you change a method in LibC, it would be reflected in both AppA and AppB.

2. Different projects, library symlinked

Basically this reflects your thought of having two different project locations for AppA and AppB - without having 2 physical LibC locations. Just take LibC (AppA) and symlink it to the new location (AppB).

Not a beautiful solution but possible (I can only speak for Unix like systems, but should work on Win as well.)

Studio Project AppA (location 1 on disk)
|
|\_app
| |_ src
|
 \_LibC (dependency for app)
  |_ src

… 

Studio Project AppB (location 2 on disk)
|
|\_app
| |_ src
|
 \_*LibC (symlinked from AppA project dir)
  |_ src

Beware that inter-project refactoring will fail in that case, e.g. you open project AppA, make substantial changes in LibC, run AppA. later you open AppB and will get compile time failures, since AppB has not been adapted to use LibC’s new APIs.

3. Library as an external dependency artefact

This can be considered by far the most "professional" way. Create your App projects, they don’t have to be in the same project tree like in option 1, and link them against a built artefact of your library LibC (aar or jar).

Ideally, this artefact is versioned and located in a (local) maven repository. That way you always have a consistent build (since you link against a specific version of your library, regardless of the development state LibC is currently in)

Studio Project AppA (location 1 on disk)
|
 \_app
  |_ src
  |_ build.gradle dependency on libc (jar/aar + version XX)

… 

Studio Project AppB (location 2 on disk)
|
|
 \_app
  |_ src
  |_ build.gradle dependency on libc (jar/aar + version YY)


Studio Project LibC (location 3 on disk)
|
 \_LibC (library module from AppA project dir)
  |_ src (in development)

As you said, Android Studio somehow forces you to create an app module first, before you can create a library module. I hope this will change anytime in the future, but it is no big deal. Just create you library module afterwards, and get rid of the app module. You can then build your library via gradle and export the artefact (aar or jar) to be used with your project.

In LibC’s build.gradle you may find something like this to deploy it to your local machine’s maven repository:

apply plugin: 'maven'
group = 'your.groupid.artefactid'
version = '0.2.0'

uploadArchives {
    repositories {
        mavenDeployer {
            repository url: 'file://' + new File(System.getProperty('user.home'), '.m2/repository').absolutePath
        }
    }
}

See http://www.alonsoruibal.com/my-gradle-tips-and-tricks/ for reference.

If you run gradle uploadArchives, it creates your artefact and pushes it into your local maven repository.

[EDIT]

There is another possibile solution, similar to option 2. Reference the library from multiple projects via gradle as a File reference, see

https://stackoverflow.com/a/21021293/1128600

This method also has the drawbacks of option 2 (no multiple API versioning, no inter-app syncing when refactoring)

Hope that summary based on personal experience helps you in finding a direction.

I personally would go with either option 1 if Apps are related, or option 3 (Maven)

like image 59
Steffen Funke Avatar answered Oct 29 '22 16:10

Steffen Funke


I used a simpler approach. Let's say you have two things:

  1. Your Application Project
  2. Your Module. Let's name it MyLib. (You can change your module name from app to MyLib by click on app>Refactor>Rename module).

Now Come to your application project, where you need to import this module. Go to Settings.gradle it should look like this

include ':app'

Now

Step 1: Add relative path of your module here. e.g in my case my project and my module was inside same directory

Projects
|
|\_MyApplication/app
|\_MyModule/MyLib 

Now You need to add MyLib Module in Settings.gradle of MyApplication. It should look like this

include ':Project','../MyModule:MyLib'

We are almost there.

Click "Sync now". Now Click on "MyApplication" go to OpenModuleSettings>Dependencies. Click on + and then 'Module Dependency'. You will see "MyLib" in option there. Just add it.

Done.

P.S: Android Studio will now show you MyLib Project inside Android studio. It isn't copied, its just showing the attached files. Your code base is at one place only.

like image 1
Ajji Avatar answered Oct 29 '22 14:10

Ajji