Skip to content Skip to sidebar Skip to footer

How Do We Reference Custom Android And Java Libraries Living Outside The Directory Of Our Main Android Project?

The conventional setup for referencing libraries has Android Studio import the libraries into the root directory of our main project. That's not really what we want as the essentia

Solution 1:

Table of Contents

  • Naming and Directory Conventions
  • Basic tricks
  • Create Main Android Project
  • Create Custom Android Library
  • Reference Custom Android Library from Main Android Project
  • Create Java Library/Module
  • Reference Java Library from Main Project
  • Please edit

Naming and Directory Conventions

Firstly we establish our naming and directory conventions (if you don't like the following, establish your own convention).

Project name: PascalCase.

..\LibraryRefDemo\MyMainProject
..\LibraryRefDemo\Libraries\MyAndroidLibrary
..\LibraryRefDemo\Libraries\MyJavaLibrary

Create New Project Wizard > Create Android Project:

Application Name: MyMainProjectProject Location: ..\MyMainProject

Package name: lowercase.

// (package name for MyMainProject's root module: "app")
au.com.example.mymainproject

// (package name for MyAndroidLibrary's root module: "malmodule")
au.com.example.malmodule

// (package name for MyJavaLibrary' module where we placed our // java code to be shared: "mjlmodule")
au.com.example.mjlmodule 

Module name: lowercase. One of the following:

app (MyMainProject's root module)
malmodule (MyAndroidLibrary's root module)
mjlmodule (The MyJavaLibrary's module where we placed our java code to be
  shared. The MyJavaModule will also contain a root "app" module 
  for reasons of gradle integration)

Basic tricks

The following basic tricks, and the subsequent step-by-step procedures, are current as of 2018-03-10 for Android Studio 3.0.1. Before going through the step-by-step procedures, the basic tricks to make this work are:

  • Use Android Studio, rather than another IDE (like IDEA IntelliJ), for creating MyMainProject, MyAndroidLibrary and MyJavaLibrary. Code and resources can be copied (e.g. using Windows Explorer) from any existing projects once the basic framework has been setup.
  • In the Main Android Project ("MyMainProject") settings.gradle (Project Settings), we reference Library modules (rather than Library Projects as such) using something like the following:

    include':app'include':malmodule'// Despite the name "project" we actually need to reference the module directory// of a project. It doesn't matter whether there is a trailing slash '/' or not.
    project(':malmodule').projectDir =
            new File(settingsDir, '../Libraries/MyAndroidLibrary/malmodule/')
    
    include':mjlmodule'// Despite the name "project" we actually need to reference the module directory// of a project. It doesn't matter whether there is a trailing slash '/' or not.
    project(':mjlmodule').projectDir =
            new File(settingsDir, '../Libraries/MyJavaLibrary/mjlmodule/')
    
  • In the Android Project ("MyMainProject") root module's build.gradle file, by default build.gradle (Module: app), add:

    dependencies {
        ...
        // Reference module rather than project.
        implementation project(':malmodule')
        implementation project(':mjlmodule')
        ...
    }
    
  • When creating MyJavaLibrary use an independently installed JDK, not Android's Embedded JDK:
    • File > Project Structure > |SDK Location| > JDK location:
      • "Use embedded JDK (recommended)": unticked.
      • C:\Program Files\Java\jdk1.8.0_161
  • Do not delete the MyJavaLibrary Project's root module, app.

The step-by-step procedure is as follows. A forward slash "/" in a string will represent a path in the Project Pane, Android View (chose from the combo box). A back slash "\" in a string will represent a path in the file system …

Create Main Android Project

Create an Android Project ("MyMainProject"):

  • Open {Android Studio} to the 'Welcome to Android Studio' screen > [Start a new Android Studio project] …
  • Wizard 'Create New Project' > |Create Android Project|:

    • Application Name (conceptually this is also the "Project Name"): MyMainProject
    • Company domain: example.com.au
    • Project Location: ..\LibraryRefDemo\MyMainProject
    • Package name: au.com.example.mymainproject
    • [Next]
  • Wizard |Target Android Devices: Select the form factors and minimum SDK|. Accept defaults (or as desire). [Next].

  • Wizard |Add an Activity to Mobile|. Empty Activity. [Next].
  • Wizard |Configure Activity|. Backwards Compatibility (AppCompat): unticked (or as desired). [Finish]
  • Add some "hello world" resources and code. In the Project Pane switch to Android View (from the combo box):

    • res/layout/activity_main.xml. Add id.

      <TextView
          android:id="@+id/mymainproject_output"
          android:layout_width="wrap_content"
    • res/values/strings.xml. Add string resource.

      <string name="mymainproject_cool_string">From My Main Project</string>
      
    • au.com.example.mymainproject.MainActivity. Reference string rescource from java code.

      publicclassMainActivityextendsActivity {
          @OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              TextViewtextView= (TextView) findViewById(R.id.mymainproject_output);
              StringsomeString= getResources().getString(R.string.mymainproject_cool_string) + "\r\n";
              textView.setText(someString); 
          }
      } 
      

      To properly import the referenced classes you may have to: insert your cursor over a TextView; alt+ enter;

  • Run against the emulator to verify OK: Run > Run app (Shift+F10)... "Select Deployment Target" > (Click on your desired Available Virtual Device) > [OK].

  • Wait for gradle to finish building. Observe the string in your application:

    From My Main Project
    

Create Custom Android Library

Firstly we create another ordinary Android Project, then we turn it into an Android Library.

Create the library as another ordinary Android Project:

  • In Android Studio close the open project, if open.
  • Open {Android Studio} to the 'Welcome to Android Studio' screen > [Start a new Android Studio project]:

    • Wizard "Create New Project", |Create Android Project|.
      • Application name: MyAndroidLibrary
      • Company domain: example.com.au
      • Project location: ..\LibraryRefDemo\Libraries\MyAndroidLibrary
      • Package name. [Edit]: au.com.example.malmodule (We are using this name rather than the default to make it clear, later on, that we are directly referencing modules rather than projects).
      • [Next]
    • Wizard |Target Android Devices|: "Select the form factors and minimum" SDK". Accept defaults (or as desired). [Next].
    • Wizard |Add an Activity to Mobile| > Empty Activity > [Next].
    • Wizard |Configure Activity|. Backwards Compatibility (AppCompat): unticked (or as desired). [Finish]
  • Wait for gradle to finish building.

  • {Android Studio} > Project Pane > Android View (from combo box) > "app" > Right Click > Refactor ... > Rename: malmodule
  • Add some hello-world type code:

    • In malmodule/res/values/strings.xml, add:

      <string name="myandroidlibrary_cool_string">From My Android Library</string>
      
    • ../res/layout/activity_main.xml (Text View). Add id.

      <TextView
          android:id="@+id/myandroidlibrary_output"
          android:layout_width="wrap_content"
    • In ..\LibraryRefDemo\Libraries\MyAndroidLibrary\malmodule\src\main\java\au\com\example\malmodule\MainActivity.java, add to onCreate method (and import relevant classes, alt+enter with cursor over TextView):

      publicclassMainActivityextendsActivity {
      
          @OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              TextViewmyText= (TextView) findViewById(R.id.myandroidlibrary_output);
              StringsomeString= getResources().getString(R.string. myandroidlibrary_cool_string) + "\r\n";
              myText.setText(someString); 
          }
      } 
      

      To properly import the referenced classes you may have to: insert your cursor over a TextView; alt+ enter;

  • Copy any existing code (and resources) from elsewhere. Copy android code into: ..\LibraryRefDemo\Libraries\MyAndroidLibrary\malmodule\src\main\java\au\com\example\malmodule

  • Verify it can run as a project: Run > Run 'malmodule'. Wait for gradle to finish building. Observe string in the emulator:

    From My Android Library
    

(Following on from above) convert a project's module to an Android library:

  • {Android Studio} > Project Panel > Android View > Gradle Scripts > build.gradle (Module: malmodule) > Double Click (to open). Then ...

    // Change ...
    apply plugin: 'com.android.application'// To ...
    apply plugin: 'com.android.library'
  • Also in build.gradle (Module: malmodule) comment out applicationID.

    ...
    android {
        compileSdkVersion 26
        defaultConfig {
    //        applicationId "au.com.example.malmodule"
            ... 
    

    Comment out rather than delete, in case we want to re-run malmodule as an ordinary Android Project for testing purposes. Android Studio 1.0 and error "Library projects cannot set applicationId"

  • Tools > Android > Sync Project with Gradle files (or click "Sync Now" link in yellow tip bar). Wait for gradle build to finish.

Reference Custom Android Library from Main Android Project

To reference your custom Android Library Project (living outside the Main Project's directory):

  • {Android Studio} > File > Open Recent > MyMainProject > 'Open Project' > [This Window].
  • Project Pane > Android View (from drop down).
  • Open MyMainProject's settings.gradle (Project Settings) file. Add :malmodule references as follows ..

    include':app'include':malmodule'// Despite the name "project" we actually need to reference the module directory// of a project. It doesn't matter whether there is a trailing slash '/' or not.
    project(':malmodule').projectDir =
            new File(settingsDir, '../Libraries/MyAndroidLibrary/malmodule/')
    
  • Open MyMainProject's root module's build.gradle file (i.e. build.gradle (Module: app)).Then add ...

    dependencies {
        ...
        // Reference module rather than project.
        implementation project(':malmodule')
        ...
    }
    
  • Tools > Android > Sync Project with Gradle files (or click "Sync Now" link in yellow tip bar).

  • Observe that malmodule's source files are now accessible via the project pane (e.g. in Android View).
  • Verify you can reference a string resource from the Library:

    • Check ..malmodule/res/values/strings.xml for the following string ...

      <string name="myandroidlibrary_cool_string">From My Android Library</string>
      
    • Check MyMainProject app/res/layout/activity_main.xml ...

      <TextView
          android:id="@+id/mymainproject_output"
          android:layout_width="wrap_content"
      ...
      
    • In Main Project app/java/au.com.example.mymainproject/MainActivity add a reference to myandroidlibrary_cool_string.

      publicclassMainActivityextendsActvity {
      
          @OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              TextViewmyText= (TextView) findViewById(R.id.mymainproject_output);
              StringsomeString= getResources().getString(R.string.mymainproject_cool_string) + "\r\n";
              someString += getResources().getString(au.com.example.malmodule.R.string.myandroidlibrary_cool_string) + "\r\n";
              myText.setText(someString); 
      
          }
      }
      
    • From your library manifest comment out the MAIN/LAUNCHER intent. Otherwise two icons for your app will appear in the App drawer.

      <activityandroid:name=".MainActivity"><!-- Don't make a main/launcher activity when being called by main app --><!--<intent-filter>--><!--<action android:name="android.intent.action.MAIN" />--><!--<category android:name="android.intent.category.LAUNCHER" />--><!--</intent-filter>--></activity>
    • Run your Main Project. Run > Run app (Shift+F10). Wait for gradle to build and for the emulator to load your app. Observe the string coming from your library is reflected in your emulator:

      From My Main Project
      From My Anroid Library
      
    • Alter a string from ..malmodule/res/values/strings.xml

      <string name="myandroidlibrary_cool_string">My Android Library XXX</string>
      
    • Run > Apply changes (Ctrl+F10). Wait for gradle to build and for the emulator to reload your app. Observe that the changed string is reflected in your emulator.

    (Google, n.d. Gradle Plugin User Guide) http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-projects (Goolge Android Tools, 2014. Develop > Tools) https://developer.android.com/studio/projects/android-library.html

Create Java Library/Module

Create a Project with a Java-Library module ...

First create an ordinary Android Project with an Android Module:

  • Close current project if open.
  • Open {Android Studio} to the 'Welcome to Android Studio' screen > [Start a new Android Studio project]:
  • Wizard "Create New Project"

    • |Create Android Project|

      • Application name: MyJavaLibrary
      • Company domain: example.com.au
      • Project location: ..\LibraryRefDemo\Libraries\MyJavaLibrary
      • Package name: au.com.example.myjavalibrary (this will be the namespace for the root module, our java code will live in another module and namespace that we'll subsequently create). [Next]
    • |Target Android Devices|. Accept defaults (or as desired). [Next]

    • |Add an Activity to Mobile| > "Add No Activity". [Finish]
  • Open Project Pane. Select "Android" View from combobox.

  • Observer there is an "app" module. We are going to create an additional module ...

Create a Java Library Module:

  • File > New ... > New Module ...
  • Wizard "Create New Module".

    • |New Module| > Java Library. [Next]
    • |Java Library| "Configure your new module".

      • Library name: mjlmodule
      • Java package name: au.com.example.mjlmodule
      • Java class name: Start
      • [Finish]

Do not delete the MyJavaLibrary Project's root module, app. If you do then, by default, your mjlmodule will run once successfully but subsequent updates to code won't be incorporated into the second and subsequent runs.

There may be a way to properly sort out the gradle files but my gradle knowledge is limited.

In your Java Library Module shove some code in:

  • In your newly created Java Class, Start, add a main method. Ensure your main method has the correct signature (specifically include "String[] args"). For example use the following class for hello world purposes. mjlmodule/java/au.com.example.mjlmodule/Start ...

    package au.com.example.mjlmodule;
    
    publicclassStart {
        publicstaticvoidmain(String[] args) {
            System.out.println(getCoolString());
        }
    
        // Must be public because we want to reference the method directly laterpublicstaticStringgetCoolString() {
            return"From My Java Library";
        }
    } 
    
  • Project Pane > Android View (from combobox) > Gradle Scripts > build.gradle (Module: mjlmodule):

    • Verify apply plugin set propery:

      apply plugin: 'java-library'
    • Verify dependency as follows:

      dependencies {
          implementationfileTree(dir: 'libs', include: ['*.jar'])
      }
      
      // You can delete or comment out ...//sourceCompatibility = "1.7"//targetCompatibility = "1.7"
    • Use an independently installed JDK, not Android's Embedded JDK.

      • File > Project Structure ... > |SDK Location| > JDK location:

        • "Use embedded JDK (recommended)": unticked.
        • C:\Program Files\Java\jdk1.8.0_161
    • Tools > Android > Sync Project with Gradle files (or click "Sync Now" link in yellow tip bar).

    • Run > Edit Configurations …

      • Click on plus + symbol > Application
      • Name: MyJavaRun
      • Main class: au.com.example.mjlmodule.Start
      • Working Directory: ... \LibraryRefDemo\Libraries\MyJavaLibrary
      • Use classpath of module: mjlmodule
      • JRE: Default
      • [OK]
    • Verify module can run...

      • On the toolbar near the run triangle ensure the " MyJavaRun" configuration is selected. Click on the run green triangle.
      • (After gradle build) observe in the "Run" pane the string output:

        From My Java Library
        

Copy java code files from elsewhere (if you have any):

  • Copy java code into: ..\LibraryRefDemo\Libraries\MyJavaLibrary\mjlmodule\src\main\java\au\com\example\mjlmodule. You might have to change package names in the copied code.

  • In Android Studio, Project Pane, observe these files show up (you might have to wait for a refresh event. Restart {Android Studio} if necessary to force a refresh).

Test run configuration OK again:

  • Make some changes to your code, e.g.:

    publicclassStart {
        publicstaticvoidmain(String[] args) {
            System.out.println(getCoolString());
        }
    
        // Must be public because we want to reference the method directly laterpublicstaticStringgetCoolString() {
            return"From My Java Library YYY";
        }
    }
    
  • On the toolbar near the run triangle ensure the " MyJavaRun" configuration is select. Click on the run green triangle.

  • Observe the updated string comes through in the "Run" pane.

    From My Java Library YYY
    

Note as of 2018-03-03 Intellij IDEA 2017.3 can't, now, run MyJavaLibrary due to not supporting the latest gradle plug-in. I'm expecting this will change from IDEA 2018.1.

See ...

It is going to stop working sometimes between 3.0-alpha2 and the final 3.0 version of the plugin.

The model that the gradle plugin export to Studio/IJ to setup the projects is changing in a breaking way. Right now it sort of sends information in both the old and new way though the former is not always accurate depending on the build setup. This is going to change soon and this will break IJ until they can get bundle the Studio plugin 3.0.

https://www.reddit.com/r/androiddev/comments/6c71av/using_android_gradle_plugin_300alpha1_with/dhssvlk/Can't use Android Gradle Plugin 3.0.+ with IntelliJ IDEA

Reference Java Library from Main Project

Reference MyJavaLibrary module ("mjlmodule") from MyMainProject:

  • {Android Studio} > File > Open Recent > [MyMainProject]. Open in [This Window].

  • In the Android Project ("MyMainProject") settings.gradle (Project Settings) add mjlmodule info:

    include':app'include':malmodule'// Despite the name "project" we actually need to reference the module directory// of a project. It doesn't matter whether there is a trailing slash '/' or not.
    project(':malmodule').projectDir =
            new File(settingsDir, '../Libraries/MyAndroidLibrary/malmodule/')
    
    include':mjlmodule'// Despite the name "project" we actually need to reference the module directory// of a project. It doesn't matter whether there is a trailing slash '/' or not.
    project(':mjlmodule').projectDir =
            new File(settingsDir, '../Libraries/MyJavaLibrary/mjlmodule/') 
    
  • In MyMainProject's root module build.gradle (Module:app), add mjmodule info:

    dependencies {
        implementation project(':malmodule')
        implementation project(':mjlmodule')
    ...
    }
    
  • Tools > Android > Sync Project with Gradle files (or click on the yellow tip bar "Sync Now").

  • Observe the mjlmodule is now referenced in th Project Pane (Android View).
  • Add a Run Configuration as specified in Create Java Project/Module above. Note we can use Android's Embedded JDK as we can run our Java module OK (presumably because we have a Project with an intact root android module).
  • Verify module can run as a Java App ...

    • On the toolbar near the run triangle ensure the " MyJavaRun" configuration is selected. Click on the run green triangle.
    • Observe in the "Run" pane the string output: "From My Java Library YYY".
  • Verify you can reference a string resource in MyJavaLibrary from MyMainProject:

    • Verify In ..LibraryRefDemo\Libraries\MyJavaLibrary\mjlmodule\src\main\java\au\com\example\mjlmodule\Start.java

      package au.com.example.mjlmodule;
      
      publicclassStart {
          publicstaticvoidmain(String[] args) {
              System.out.println(getCoolString());
          }
      
          // Must be public because we want to reference the method directly laterpublicstaticStringgetCoolString() {
              return"From MyJavaLibrary YYY";
          }
      }  
      
    • Verify In MyMainProject app/res/layout/activity_main.xml

      <TextView
          android:id="@+id/mymainproject_output"
          android:layout_width="wrap_content"
      ...
      
    • Add some code in MyMainProject to pickup code from MyJavaLibary. In MyMainProject/app/java/au.com.example.mymainproject/MainActivity add a reference to the mjlmodule string ...

      publicclassMainActivityextendsActivity {
      
          @OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              TextViewtextView= (TextView) findViewById(R.id.mymainproject_output);
              StringsomeString= getResources().getString(R.string.mymainproject_cool_string) + "\r\n";
              someString += getResources().getString(au.com.example.malmodule.R.string.myandroidlibrary_cool_string) + "\r\n";
              someString += au.com.example.mjlmodule.Start.getCoolString() + "\r\n"; 
              myText.setText(someString);
      
          }
      }
      
    • Run MyMainProject. On the toolbar select the "app" configuration. Click the Green arrow. If you get an error "you can't install" then Build > Clean MyMainProject.

    • Observe the string coming from your library is reflected in your emulator (or connected device).

      From MyMainProject
      From My Android Library XXX
      From My Java Library YYY
      
  • Modify a string in MyJavaLibrary. ...\LibraryRefDemo\Libraries\MyJavaLibrary\mjlmodule\src\main\java\au\com\example\mjlmodule\Start.java

    publicstaticStringgetCoolString() {
        return"From My Java Library ZZZ";
    } 
    
  • Run > Apply changes. Observe that the string is reflected in your emulator (or connected device).

    From MyMainProject
    From My Android Library XXX
    From My Java Library ZZZ
    

Please edit

Please be bold in editing the answer if:

  • There are errors;
  • It becomes out of date;
  • You feel something could be made clearer;
  • You can simplify the steps; or
  • You can think of some other good reason to make an edit.

Updates:

  • 2018-03-14 04:52Z. First release ... having followed procedures once and having reviewed it for completeness and correctness (some small corrections were made). JLB.
  • 2018-10-16 04:11Z. To "Reference Custom Android Library from Main Android Project" added a step to comment out Custom Android Library's MAIN/LAUNCHER intent.

Post a Comment for "How Do We Reference Custom Android And Java Libraries Living Outside The Directory Of Our Main Android Project?"