Add project as library – Titanium module (Android)

Native Android application can include other projects as library, when they need that particular SDK library functionalities – using Eclipse, right click project > Properties > Android > Library. However for Titanium module, there’s no option to add other projects as library. Instead, we need to include the whole project itself into the module project directory.

For example, I’m creating GooglePlayServices module, so I need to copy files from ANDROID_SDK_DIR/extras/google/google_play_services/libproject/google-play-services_lib/ into the module folder

export MODULE_DIR=~/Workspace/ti.googleplayservices/
cd $ANDROID_SDK_DIR
cp -r libs/*.jar $MODULE_DIR/lib
cp -r res/ $MODULE_DIR/platform/android/
cp -r src/ $MODULE_DIR/src/

Most of the time, the library that being included will be missing R.java and BuildConfig.java file. Depending on the library itself, create those files manually. For this GooglePlayServices module, the generated resource file (R.java) is located at com.google.android.gms namespace:

touch $MODULE_DIR/src/com/google/android/gms/R.java

(for Facebook SDK that I created sometime ago, it’s at com.facebook.android)

Now, again depending on the library we’re including, the content of R.java can be found either from the source code (like Facebook SDK) or from the documentation (GooglePlayServices).

Originally, R.java is generated by Android build tool when building APK file for a project, but since we’re building a Titanium module, R.java cannot be generated, since it’s value might clash with the actual project that use this module. Values inside R.java are generated from the XML resources (such as strings.xml, values.xml, layout.xml), or graphic files (icons / images files, also known as drawables).

The difference between this file and the generated one, is that we need to initialize it to populate its values. By using TiRHelper, we will get and assign all the values at runtime.

package com.google.android.gms;

import org.appcelerator.titanium.util.TiRHelper;
import org.appcelerator.titanium.util.TiRHelper.ResourceNotFoundException;

public class R {

    public static class attr {
        public static int adSize;
        public static int adUnitId;
        public static int allowShortcuts;
        // ... more ...
    }

    public static class color {
        // ...
    }

    public static class drawable {
        // ...
    }

    public static class id {
        // ...
    }

    public static class integer {
        // ...
    }

    public static class string {
        // ...
    }

    public static class styleable {
        // ...
        public static final int[] AdsAttrs = {
            styleable.AdsAttrs_adSize,
            styleable.AdsAttrs_adSizes,
            styleable.AdsAttrs_adUnitId,
        };
        // ... more ...
    }

    public static void initialize() {
        R.attr.adSize = getResource("attr.adSize");
        R.attr.adUnitId = getResource("attr.adUnitId");
        R.attr.allowShortcuts = getResource("attr.allowShortcuts");
        // ... more ...
    }

    private static int getResource(String path) {
        int id = 0;
        try {
            id = TiRHelper.getResource(path);
        } catch (ResourceNotFoundException e) {}
        return id;
    }
}

Then, in the main module class, don’t forget to call initialize() method on app creation.

@Kroll.onAppCreate
public static void onAppCreate(TiApplication app) {
    R.initialize();
}