明壁幕府忍法帳 > Aptana Index > Home > Titanium SDK > Titanium SDK How-tos > Extending Titanium Mobile > Android Module Development Guide > Android Module Project

2020.10.07 Ver.56 (2021.1.16)

Android Module Project

Introduction

This guide covers how to manage your module project as well as how to add third-party frameworks and bundle assets with your module.  You can use Studio, Eclipse or the Appc-CLI to build Android modules.

Prerequisites

To develop an Android-based Module, you need to install the following tools and setup a few additional environment variables:

If you want to use Studio, install:

Project Structure

A number of files and directories work together to define our module and what it does. Let's take a quick look at each of them:

File/Directory Description
LICENSE The module's full license text; this will be distributed with the module to let other developers know how they can use and redistribute it.
assets/

The directory where you can place module assets such as images. The files in this directory are added as JAR resources which you can be fetch in Java via the ClassLoader.getResourceAsStream() method. They're also copied to the APK's "assets" folder.

documentation/ The directory where you should place your module documentation for end-users. The file index.md is a Markdown-formatted template file that you should use when writing your module documentation. You may also write your documentation using the TDoc Specification. You can safely ignore this directory if you do not intend to distribute your module.
example/ The directory where your module example(s) should go. The file app.js will be generated to include a sample loading of your module in a test window. This file can be used for quickly testing your module as well as give an example to end-users on how to use your module. This directory is distributed with your module.
Resources/ Supported as of Titanium 9.0.0. Files placed in this directory will be copied to the Android app's root "Resources" directory when built, making them accessible to the Titanium app's JavaScript files. These files are also accessible in Java via the AssetManager class.
android/build.gradle As of Titanium 9.0.0, this optional gradle file allows a module to define its dependencies.
android/lib/

Place any third-party JAR dependencies here and they will be bundled up as a part of your module automatically.

As of Titanium 9.0.0, it is highly recommended to reference dependencies via "build.gradle" instead to avoid dependency collision with other modules.

android/manifest A special file that describes metadata about your module and used by the Titanium compiler. This file is required and is distributed with your module. 
android/platform/android/AndroidManifest.xml As of Titanium 9.0.0, you can optionally specify the module's custom AndroidManfiest.xml here. Alternatively, you can do the same within the timodule.xml as documented below.
android/platform/android/aidl/ As of Titanium 9.0.0, you can add Java code generation templates here, as defined by the Android Developer: AIDL guide.
android/platform/android/assets/ As of Titanium 9.0.0, you can optionally provide files that will be copied to the APK's root "assets" folder here.
android/platform/android/jniLibs/ As of Titanium 9.0.0, you can add C/C++ *.so libraries to be bundled with the module. These libraries must placed under subdirectories named after their respective architecture such as armeabi-v7a, arm64-v8a, x86, and x86_64.
android/platform/android/rs/ As of Titanium 9.0.0, you can add RenderScript files here as defined by the Android Developer: RenderScript guide.
android/platform/android/res/ Optional folder where you can add Android resource files such as drawables, layouts, mipmaps, values, etc. as defined in the Android Developer: Providing Resources guide.
android/src/ Folder containing your Java source files for the module. Can contain Kotlin source files as of Titanium 9.0.0. This directory is not distributed with your module.
android/timodule.xml A place to put custom activities and general XML that will end up in the AndroidManifest.xml of apps. Read more about this file in the tiapp.xml and timodule.xml reference.

The CLI creates a module project that contains multiple platforms. Each platform contains its own folder with platform-specific resources and common folders for assets, documentationexample, and Resources.

Build properties file

Icon

This was deprecated since 5.0.0.


The build.properties file contains build variables used by the Ant CLI. Using the build.properties is deprecated in favor of the unified build-command appc ti build -p android --build-only.

Variable
Description
Example
titanium.platform Path to the Titanium SDK android folder /Users/<USERNAME>/Library/Application Support/Titanium/mobilesdk/osx/<VERSION>/android
android.platform Path to the Android SDK platforms folder /Users/<USERNAME>/opts/android-sdk/platforms/android-25
google.apis Path to the Google APIs add-ons folder /Users/<USERNAME>/opts/android-sdk/add-ons/addon-google_apis-google-25
android.ndk Path to the Android NDK (if needed) /Users/<USERNAME>/opts/android-ndk

 

Manifest file

Titanium module metadata is described in a special text file named manifest. This file is a simple key/value property format.

Before you distribute your module, you must edit this manifest and change a few values. Some of the values are pre-generated and should not be edited.  These are noted with the comment before them. In the manifest file, any line starting with a hash character (#) is ignored. The following are the descriptions of each entry in the manifest:

Key

Description/Purpose

version

This is the version of your module. You should change this value each time you make major changes and distribute them. Version should be in the dotted notation (X.Y.Z) and must not con-tain any spaces or non-number characters.

architectures The binary architectures the module supports as a delimited list. Example: x86 arm64-v8a

description

This is a human-readable description of your module. It should be short and suitable for display next to your module name.

author

This is a human-readable author name you want to display next to your module. It can simply be your personal name, such as "Jon Doe" or an organizational name such as "Axway Appcelerator".

license

This is a human-readable name of your license. You should use a short description such as "Apache Public License", "MIT" or "Commercial".

copyright

This is a human-readable copyright string for your module. For example, "Copyright (c) 2020 by Axway Appcelerator, Inc."

name

This is a read-only name of your module that is generated when you created your project. You must not edit this value.

moduleid

This is a read-only module id of your module that is generated when you created your project. You should not edit this value. NOTE: you must generate a unique id. We recommend using your reverse-DNS company name + module_name as a pattern to guarantee uniqueness. If you must edit this value, you must also edit the value in your module implementation file.

guid

This is a read-only unique module id for your module that is generated when you created your project. You must not edit this value.

platform

This is a read-only platform target of your module that is generated when you created your project. You must not edit this value.

minsdk

The is a generated value for the minimum Titanium SDK version that was used when creating your module. The current minimum version for new Android modules is 7.0.0.

respackage

This setting only applies to Titanium versions older than 9.0.0.

This is specific package name to generate a R.java. If you got exception like java.lang.NoClassDefFoundError: com.example.mypackage.R$layout then add the following entry to the your module manifest file: respackage: com.example.mypackage . This will generate a corresponding java R file com.example.mypackage.R.java

CLI tasks

Create a new module project

To create a new module project, run the following Appcelerator CLI command: 

appc new -d /PATH/TO/WORKSPACE -n <MODULE NAME> --id <MODULE ID>
 
$ appc new -n <MODULE NAME> --id <MODULE ID>
Appcelerator Command-Line Interface, version 7.1.2
Copyright (c) 2014-2018, Appcelerator, Inc.  All Rights Reserved.
? What type of project are you creating?
  Native App
  Arrow App
❯ Titanium Module (timodule)
  Apple Watch App

If you omit any of the options, the CLI will prompt you to enter them.

Build and package the module

To build and package a module, run ti build in the android directory.

cd /<PATH_TO_MODULE_PROJECT>/<MODULE_NAME>/android
appc run -p android --build-only

After the build completes, you should have a ZIP file in the android/dist directory and see the following message in the console: 

** BUILD SUCCEEDED **

With the ZIP file, you can either:

  • Uncompress it in the Titanium SDK home path to install the module globally for all your Titanium applications
  • Uncompress it in a Titanium project's parent directory to install the module locally for that one Titanium application
  • Distribute the ZIP file

Clean the project

Earlier, you could clean your module with ant clean. These days, using the Appc-CLI, the build will be cleaned automatically before a new build is made.

Studio tasks

Create a new module project

  1. From the menu, select File > New > Mobile Module Project to open the New Mobile Module Project dialog.
  2. In the Project name field, enter a name for the module.
  3. In the Module ID field, enter a module ID for the module.
  4. In Deployment Targets, select Android.
  5. Click Next.
  6. In the Module Manifest File page, enter information about your module, such as the license information, version number, etc.  You can also edit this information in the manifest file later.
  7. Click Finish.

Build and package the module

You can either use Studio's launch toolbar or use Ant from the right-click context menu.

Studio Toolbar

  1. Select your module folder in the Project Explorer view.
  2. Verify Package and Android Module are displayed in Launch Mode and Launch Target, respectively.
  3. Click the Package icon to open the Package Android Module dialog.
  4. In Output Location, select either
    1. Titanium SDK to install the module in the Titanium SDK home path to be accessed by any Titanium application
    2. Mobile App Project and choose an application to install the module locally that can be accessed by one that Titanium application
    3. Location and enter a path to copy the ZIP file to for distribution
  5. Click Finish.

In the Console view, you will see the build log output.  After the build completes, the package (ZIP file) will be in the module's android/dist folder.

Test the module

To test a module:

  1. Create a new Titanium Classic or Alloy project.
  2. Install the module to either the Titanium SDK home directory or in the project.
  3. Add the module as a dependency to the project.
  4. Load the module and make module API calls.

Debug the module

The best way to debug your Android modules right now is a bit old fashioned. When there is a problem or unexpected behavior in your module, use log statements to trace through your code's execution. The Java Log class offers several static methods for writing to the log. It is considered a best practice to define a LCAT or TAG variable at the top of your class, and to use that as the first parameter to all calls to Log.

private static final String TAG = "FooProxy";
 
@Kroll.method
public void fooFunction(String arg)
{
    Log.i(TAG, "fooFunction received: " + arg);
}

Adding 3rd party libraries

Icon

As of Titanium 9.0.0, you can no longer use Google's deprecated Support libraries. You must use the AndroidX libraries instead.

 

Gradle Dependencies

As of Titanium 9.0.0, you can reference libraries via gradle by adding a build.gradle file to the module's root android directory. This is the preferred way of adding libraries because the gradle build system will automatically include a dependency's dependencies and resolve version conflicts.

An example can be found here: ti.map/android/build.gradle

The below is an example build.gradle file which provides access to the Google "Material Components" library.

dependencies {
    implementation 'com.google.android.material:material:1.1.0'
}

 

Local Dependencies

To use a third-party JAR in your module, add the JAR file to the module's lib directory (not the libs directory), so it can be copied over during the module's build process and linked when building the application.  If you are using Studio, you need to add the JAR as a dependency to the module project before importing the package and making API calls.

To add a JAR as a dependency in Studio:

  1. Right-click the module project (root folder) and select Properties to open the project's properties dialog.
  2. In the left pane, select Java Build Path.
  3. In the right pane, click the Libraries tab.
  4. Click the Add External JARs... button to open the JAR Selection dialog.
  5. Navigate to the module's android/lib folder and select the JAR to add.
  6. Click Open.  The JAR should be added to the JARs list.
  7. Click OK to dismiss the dialog.

With Titanium 6.1.1 - 8.3.1, you can also copy AAR (Android Archive) library files to the module's lib directory. However, this is not supported as of Titanium 9.0.0, which requires you to reference these AAR libraries via a build.gradle file instead.

Where do i get .aar files?

Icon

Most third-party libraries can be downloaded from either GitHub or from one of the popular repositories like jCenter or Maven Central. Copies of the Android Support Libraries can be found inside your Android SDK directory under <andriod-sdk>/extras/android/m2repository/com/android

Adding Android Libraries to Studio

To properly resolve any imports of your used Android Libraries in Studio, you need to add the JARs they are contained in to Studio's Java build path. Before you add any import statements to your code, build the project at least once. This is required to process the AAR files and extract the JAR files they contain. After that, add the required JARs to Studio just as described in the Add a Third-Party JAR section of this guide. The extracted JAR files can be found under build/android/intermediates/exploded-aar. There you'll find a directory for each AAR file. Inside each of those directories, add the classes.jar and any additional JAR files under the lib directory.

Bundling files

For Android modules, you can either add assets in the module's assets folder or android/platform folder.

Module "assets" folder

Files in the module's assets folder are added as JAR resources. To access these files, use the Android Class's getResource() method to retrieve a URL object or getResourceAsStream()  method to retrieve an InputStream object. 

// original file was in assets/image.png
URL url = getClass().getClassLoader().getResource('assets/image.png');
Log.i('GETFILE', url.toString());
Icon

The README file and JavaScript files (any file with a .js extension) in the assets folder are not added to the JAR library.

Module "platform/android/res" folder

Add any of the resource directories defined in Android Developer: Providing Resources to add drawables, layouts, values, etc. to the built app. To access these files, you can use the Titanium SDK TiRHelper helper class.

// original file was in android/platform/android/res/drawable/image.png
int result = 0;
try {
    result = TiRHelper.getApplicationResource('drawable.image');
    Log.i("GOODSTUFF", new Integer(result).toString());
} catch (ResourceNotFoundException e) {
    Log.e('BADSTUFF', '[ERROR] EXCEPTION -- RESOURCE NOT FOUND');
}

Format / Lint source-code

The Titanium SDK uses clang-format to have a unified code-style in its source-code (clang-format for iOS and Android, ESLint for the CLI). You can do the same by following the following few steps:

  1. Copy the .clang-format file from here to the "android/" directory of your module project, e.g. <module-root>/ios/.clang-format
  2. Install the clang-format CLInpm install -g clang-format
  3. Optional: Ensure that you have your module project in Git to be able to restore the old files in case you do not like the predefined format 

  4. Format your source with: clang-format -style=file -i src/<yourmodule>/*.java
  5. Thats it! All *.java files have been formatted.

Now that you have a format, you can also extend your .clang-format with more formatting rules or adjust existing ones to match your own code style.

Troubleshooting

Conflicting JAR files / Google Play Services

When building an application that includes two or more modules that contains the same library, in particular, the google-play-services.jar, the JAR files may conflict indicating that each module is using a different version of the library.

Error Log

Prior to Titanium SDK 7.0.0, to resolve this issue, you can either delete one of the JAR files from one of the modules or copy the JAR file from one module's lib folder to the other's to make both versions the same. This solution only works on a per-application basis and is not a global solution. In Titanium 7.0.0 and later, use the ti.playservices module to handle play services dependencies centralized. Simply add it to your timodule.xml and users will be notified if they do not include the module in their project.

Android NDK build fails

If the Android NDK build fails, it can be because of various reasons:

  • Your module has compile errors. Usually the build on the "javac" compile step already, but in case it does not, scroll up in the logs to see the actual error)
  • Your NDK version is outdated (Check for the latest version here)
  • Your project path contains spaces, which is not recommended for projects in general but especially causes build failures like /android-ndk/build/core/build-local.mk:158: *** Android NDK: Aborting, which is an Android NDK error for spaces in projects OR invalid directories for the Android NDK. Please note that spaces in a sub-directory can also cause this.

In any case, ensure to run your Titanium module build with log-level "trace" (e.g. appc run -p android -build-only -l trace) to see the whole build command. If you find issues that are not listed here, feel free to let us know via JIRA or TiSlack.