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: MyMainProject
Project 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.
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.mymainproject_output);
String someString = 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):
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView myText = (TextView) findViewById(R.id.myandroidlibrary_output);
String someString = 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.
public class MainActivity extends Actvity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView myText = (TextView) findViewById(R.id.mymainproject_output);
String someString = 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.
<activity android: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:
Create a Java Library Module:
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;
public class Start {
public static void main(String[] args) {
System.out.println(getCoolString());
}
// Must be public because we want to reference the method directly later
public static String getCoolString() {
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 {
implementation fileTree(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.
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...
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.:
public class Start {
public static void main(String[] args) {
System.out.println(getCoolString());
}
// Must be public because we want to reference the method directly later
public static String getCoolString() {
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;
public class Start {
public static void main(String[] args) {
System.out.println(getCoolString());
}
// Must be public because we want to reference the method directly later
public static String getCoolString() {
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 ...
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.mymainproject_output);
String someString = 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
public static String getCoolString() {
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.