0

I want to create few library (core and modules), add all this libraries to application and call methods from modules in core library. All modules should be optional. For example, as I see it:

Application build.gradle:

compile('core-library:1.0@aar')
compile('module1-library:1.0@aar')
compile('module2-library:1.0@aar')
compile('module3-library:1.0@aar')

In every module define class and methods with same name:

public class ModuleClass {
    public int moduleMethod1() {
        // Do something and return result
        return 1;
    }

    public String moduleMethod2() {
        return "Some String";
    }
}

In core library:

for(ModuleClass c : getAllModules()) {
    Log.d("tag", "Result: " + c.moduleMethod1() + " / " + c.moduleMethod2();
}

Sure that is just pseudo-code. How to implement it or something like?

Updated: Core module build.gradle:

apply plugin: 'com.android.library'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.3"

    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        buildConfigField "String[]", "KNOWN_MODULES", "{" +
                "\"module1\"," +
                "\"module2\"" +
                "}"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compileOnly project(':module1')
    compileOnly project(':module2')
    testCompile 'junit:junit:4.12'
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
}
BArtWell
  • 4,176
  • 10
  • 63
  • 106

1 Answers1

1

You might try something like adding a List<Class> in the core-library. You have to be really careful when you try to load the list but you should be able to do it.

First your moduleN-library needs to be compileOnly so it won't be bundled with the core-library.

Then in your core-library keep a singleton that safely lists all possible module classes.

package com.jbirdvegas.test;

import java.util.HashMap;
import java.util.Map;

public class ModuleClassManager {
    private static final Object LOCK = new Object();
    private static ModuleClassManager instance;

    private Map<Class, Methods> moduleClasses = new HashMap<>();

    private ModuleClassManager() {
        try {
            moduleClasses.put(MayNotExist1.class, new MayNotExist1());
        } catch (Exception ignored) {
        }
        try {
            moduleClasses.put(MayNotExist2.class, new MayNotExist2());
        } catch (Exception ignored) {
        }
        try {
            moduleClasses.put(MayNotExist3.class, new MayNotExist3());
        } catch (Exception ignored) {
        }
    }

    public static ModuleClassManager getInstance() {
        if (instance == null) {
            synchronized (LOCK) {
                instance = new ModuleClassManager();
            }
        }
        return instance;
    }

    public void callMethodOnAll() {
        moduleClasses.forEach((aClass, methods) -> methods.methodOne());
    }

    // the below interface in the real world would be located
    // in the `core-library` and the classes that implement the
    // interface, `Methods` in this example, would exist in the
    // module's they represent.
    interface Methods {
        void methodOne();
    }

    class MayNotExist1 implements Methods {
        @Override
        public void methodOne() {
        }
    }

    class MayNotExist2 implements Methods {
        @Override
        public void methodOne() {
        }
    }

    class MayNotExist3 implements Methods {
        @Override
        public void methodOne() {
        }
    }
}

Or... use OSGi. OSGi is more complicated to setup however it handles this usecase extremely well.

JBirdVegas
  • 10,855
  • 2
  • 44
  • 50
  • Thank you. Is `compileOnly` can be used for modules? Code `compileOnly project(':mymodule1')` generate error `Could not find method compileOnly() for arguments [project ':mymodule1'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler`. Or I need manually compile aar file every time for all modules? – BArtWell Jan 04 '17 at 18:13
  • Show your full build.gradle file the `java` plugin should add the `compileOnly` sourceset – JBirdVegas Jan 04 '17 at 19:12
  • Please see updated question. I add full build.gradle for core module. – BArtWell Jan 08 '17 at 16:28