Welcome to follow the official wechat account: FSA Full stack action 👋

A, RePluginX

Because RePlugin does not support AndroidX, there have been no new Commits or a number of issues on Github, suggesting that the project has been abandoned. RePlugin will be used by companies developing it, but they will need to customise it, and the chances of submitting pr to the authorities will be a bit of a slap in the head. Instead, do a good job of maintaining a more functional RePluginX based on it for those who need it

Note: If RePlugin is up and running again, adding new features that satisfy your needs, I strongly recommend using it. Open source is not easy.

1. Version information

  • RePlugin Base version:2.3.4
  • RePluginX Release:v0.0.4
  • GitHub address: github.com/GitLqr/RePl…

2. New features

RePluginX supports the following new features over RePlugin:

  • ✅ also supports Android support and AndroidX
  • ✅ Supports screen orientation for pit activities
  • 📝 to be continued…

Note: I will continue to add new features to RePluginX in the future in this article.

Lib library compatible with AndroidX

RePluginX can be used in Support projects as well as android X projects. The principle is simple: the runtime determines the type of Android compatible package the project is using and loads one of the types of code.

Principle :(host/plugin) project class loaders only load one type of support or androidx, the other type cannot be loaded by class loaders.

The key implementation steps are as follows:

1. Introduce Android compatible packages

Provided/compileOnly imports support-V4 and Androidx. appCompat at the same time so lib can write code using the respective compatible package apis. In addition, support-V4 and Androidx. appcompat classes will not be included in the compilation to avoid class conflicts during project compilation.

provided 'com. Android. Support: support - v4:25.2.0'
provided 'androidx. Appcompat: appcompat: 1.1.0'
provided 'androidx. Localbroadcastmanager: localbroadcastmanager: 1.0.0'
Copy the code

Note: because the support – contains localbroadcastmanager v4, and androidx. Appcompat does not contain, so need to separate into androidx. Localbroadcastmanager.

2. Determine the types of compatible Android packages

RePuginX’s lib library needs to be run by reflection to determine which android compatible package type (host/plugin) project is actually using. The logic code is as follows:

/** * Compatibility layer configuration **@author LQR
 * @since2021/12/8 * /
public final class CompatConfig {

    private static volatile CompatConfig sInstance;

    public static final boolean DEPENDENCY_ANDROIDX;
    public static final boolean DEPENDENCY_SUPPORT;

    static {
        / / FIX: host engineering (shell) do not necessarily rely on androidx. Appcompat, but will depend on the androidx. Localbroadcastmanager
        DEPENDENCY_ANDROIDX = findClassByClassName("androidx.localbroadcastmanager.content.LocalBroadcastManager");
        DEPENDENCY_SUPPORT = findClassByClassName("android.support.v4.content.LocalBroadcastManager");
        // DEPENDENCY_ANDROIDX = findClassByClassName("androidx.fragment.app.FragmentActivity");
        // DEPENDENCY_SUPPORT = findClassByClassName("android.support.v4.app.FragmentActivity");}...private static boolean findClassByClassName(String className) {
        boolean hasDependency;
        try {
            Class.forName(className);
            hasDependency = true;
        } catch (ClassNotFoundException e) {
            hasDependency = false;
        }
        returnhasDependency; }}Copy the code

3. Replace directly introduced Android compatible package code

(host/plugin) {host/ host/ broadcastManager / @nonnull; For LocalBroadcastManager, a layer of packaging is required to load the corresponding LocalBroadcastManager for different compatible packages. LocalBroadcastManager = broadcastManager = BroadcastManager = BroadcastManager = BroadcastManager = BroadcastManager = BroadcastManager = BroadcastManager;

/** * LocalBroadcastManager compatibility layer **@author LQR
 * @since2021/12/8 * /
public abstract class LocalBroadcastManager {

    public static LocalBroadcastManager getInstance(Context context) {
        if (CompatConfig.DEPENDENCY_ANDROIDX) {
            return new LocalBroadcastManagerAndroidX(context);
        } else if (CompatConfig.DEPENDENCY_SUPPORT) {
            return new LocalBroadcastManagerSupport(context);
        }
        return null;
    }

    public abstract void registerReceiver(BroadcastReceiver receiver, IntentFilter filter);

    public abstract void unregisterReceiver(BroadcastReceiver receiver);

    public abstract boolean sendBroadcast(Intent intent);

    public abstract void sendBroadcastSync(Intent intent);

}

/** * AndroidX LocalBroadcastManager **@author LQR
 * @since2021/12/8 * /
public class LocalBroadcastManagerAndroidX extends LocalBroadcastManager {

    private final androidx.localbroadcastmanager.content.LocalBroadcastManager localBroadcastManager;

    public LocalBroadcastManagerAndroidX(Context context) {
        localBroadcastManager = androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context);
    }

    @Override
    public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        localBroadcastManager.registerReceiver(receiver, filter);
    }

    @Override
    public void unregisterReceiver(BroadcastReceiver receiver) {
        localBroadcastManager.unregisterReceiver(receiver);
    }

    @Override
    public boolean sendBroadcast(Intent intent) {
        return localBroadcastManager.sendBroadcast(intent);
    }

    @Override
    public void sendBroadcastSync(Intent intent) { localBroadcastManager.sendBroadcastSync(intent); }}/** * AndroidSupport LocalBroadcastManager **@author LQR
 * @since2021/12/8 * /
public class LocalBroadcastManagerSupport extends LocalBroadcastManager {

    private final android.support.v4.content.LocalBroadcastManager localBroadcastManager;

    public LocalBroadcastManagerSupport(Context context) {
        localBroadcastManager = android.support.v4.content.LocalBroadcastManager.getInstance(context);
    }

    @Override
    public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
        localBroadcastManager.registerReceiver(receiver, filter);
    }

    @Override
    public void unregisterReceiver(BroadcastReceiver receiver) {
        localBroadcastManager.unregisterReceiver(receiver);
    }

    @Override
    public boolean sendBroadcast(Intent intent) {
        return localBroadcastManager.sendBroadcast(intent);
    }

    @Override
    public void sendBroadcastSync(Intent intent) { localBroadcastManager.sendBroadcastSync(intent); }}Copy the code

The LocalBroadcastManager package in the Lib library should be replaced.

Note: Gradle plugin (host/plugin) contains a number of processing sections for support. Add the same processing code to AndroidX. RePluginX: replugin-host-gradle: Replugin-plugin-gradle

3. Direction of pit screen

RePlugin, which is in the TV business, needs to be customised because its products must be fixed to a landscape screen, and its default Activity pit is vertical. In order to meet the needs of Moblie and TV, we added the screenOrientation configuration to the host gradle configuration. The host project can configure the screenOrientation of the pit according to the needs of the project.

apply plugin: 'replugin-host-gradle'
repluginHostConfig {
    screenOrientation = 'landscape' // Direction of pit Activity (portrait/landscape). }Copy the code

To do this, simply modify (host) the Gradle plugin in two places:

  1. RePlugin.groovyfile
class RepluginConfig {

    /** * Screen orientation * Note: The default is portrait, which can be configured as landscape. * /
    def screenOrientation = "portrait". }Copy the code
  1. ComponentsGenerator.groovyfile
class ComponentsGenerator {
    // def static final oriV = 'portrait'
    def static oriV = 'portrait'

    def static generateComponent(def applicationID, def config) {
        updateConfig(applicationID, config)
        ...
    }

    def static generateMultiProcessComponent(def applicationID, def config) {
        updateConfig(applicationID, config)
        ...
    }

    /** * Update the configuration */
    def static updateConfig(def applicationID, def config){
        oriV = config.screenOrientation
    }
}
Copy the code

Release the JITPack

There are many tutorials on the web for publishing the JitPack, and the basic steps are as follows:

Step 1: Add the following plugin dependencies to build.gradle:

classpath 'com. Making. Dcendents: android - maven - gradle - plugin: 2.1'
Copy the code

Build. Gradle = build.gradle = build.gradle = build.gradle = build.gradle

apply plugin: 'com.github.dcendents.android-maven'
group='com.github.username' // For example, com.github.GitLqr
Copy the code

Create a release on the Project’s Github page:

Find username/repoName on jitpack. IO.

Note: when release is just created, it still needs to wait for jitpack. IO to queue fetching, which takes about 5-10 minutes. You can judge the current fetching state by the Status bar in the figure.

Step 5: Click the “Get It” button and add dependencies to the project according to the dependency guidelines:

This is the jitPack release process. If you are keen, you may notice a Subproject drop-down button that looks something like this when you expand it:

It should be noted that, unlike RePluginX, where RePluginX is a lib library (module), there is no Subproject drop-down button. RePluginX This repo contains two lib libraries and two gradle plugins:

  • 【 replugin – host – gradle 】
  • 【 replugin – host – library 】
  • 【 replugin plugin – gradle 】
  • 【 replugin plugin – library 】

Yes, jitpack. IO supports a repo multi-module distribution, and a few Google articles suggest that both gradle plug-ins and lib libraries are configured in the same way. Jitpack. IO automatically recognizes segmentation when fetching, but the dependency rules change:

// A repo corresponds to a lib library
compile 'com.github.USERNAME:REPO:VERSION'

// One repo corresponds to multiple lib libraries
compile 'com.github.USERNAME.REPO:MODULE:VERSION'
Copy the code

Replugin-host-gradle, replugin-host-library… Build. Gradle is configured as follows:

apply plugin: 'com.github.dcendents.android-maven'
group='com.github.GitLqr'
Copy the code

After that, their dependency configurations are as follows:

classpath 'com. Making. GitLqr. RePluginX: replugin - host - gradle: v0.0.4'
implementation 'com. Making. GitLqr. RePluginX: replugin - host - library: v0.0.4'
classpath 'com. Making. GitLqr. RePluginX: replugin plugin - gradle: v0.0.4'
implementation 'com. Making. GitLqr. RePluginX: replugin plugin - library: v0.0.4'
Copy the code

Jitpack. IO Publishing multiple modules in a repo

  • Jitpack. IO/docs/ANDROI…
  • Jlelse. Blog/dev/multi – m…
  • Stackoverflow.com/questions/4…

Manage multiple projects

RePluginX and RePlugin are slightly different in engineering:

Name RePlugin RePluginX
replugin-host-gradle project module
replugin-host-library project module
replugin-plugin-gradle project module
replugin-plugin-library project module
replugin-sample/host project project
replugin-sample/plugin/plugin-demo1 project project
replugin-sample/plugin/plugin-demo2 project project
replugin-sample/plugin/plugin-demo3-kotlin project project
replugin-sample/plugin/plugin-webview project project
  • In the RePlugin project, RePlugin is just a directory that contains n projects, For example, [replugin-host-library] [replugin-plugin-library] are two projectssettings.gradleFile)
  • In the RePluginX project, RePluginX is a real project, and [Replugin-host-library] [Replugin-plugin-library] is two modules of the RePluginX project. RePluginX has four modules, namely [replugin-host-gradle] [replugin-host-library] [replugin-plugin-gradle]

Here’s the interesting thing: RePlugin is just a directory, which means that all the projects underneath it must be coded and debugged in a separate AndroidStudio, which might not be a big deal if you have plenty of ram and multiple monitors. But if you don’t have the above conditions, you will feel quite uncomfortable. In addition, I personally think it would be more comfortable for a project to manage hosts and plug-ins in a single AS window (I prefer an AS window for a project, not a specific project). RePluginX fixes this problem with the includeBuild provided by Gradle 3.1. Here is the contents of settings.gradle in the RePluginX root:

// Current project Module
include ':replugin-host-gradle'
include ':replugin-host-library'
include ':replugin-plugin-gradle'
include ':replugin-plugin-library'

// Support Demo project
includeBuild('./replugin-sample/host')
includeBuild('./replugin-sample/plugin/plugin-demo1')
includeBuild('./replugin-sample/plugin/plugin-demo2')
includeBuild('./replugin-sample/plugin/plugin-demo3-kotlin')
includeBuild('./replugin-sample/plugin/plugin-webview')
includeBuild('./replugin-sample-extra/fresco/FrescoHost')
includeBuild('./replugin-sample-extra/fresco/FrescoPlugin')

// AndroidX Demo project
includeBuild('./repluginx-sample/host')
includeBuild('./repluginx-sample/plugin/plugin-demo1')
Copy the code

Settings. gradle = settings.gradle = settings.gradle = settings.gradle = settings.gradle = settings.gradle = settings.gradle = settings.gradle

// replugin-sample/host/settings.gradle
rootProject.name = 'replugin-sample.host'

// repluginx-sample/host/settings.gradle
rootProject.name = 'repluginx-sample.host'
Copy the code

AS a result, after the RePluginX project is opened and loaded, you can see the following configuration list appear in the run window:

It is highly recommended that business projects also follow the RePluginX approach to managing multiple projects, using includeBuild to manage host projects and plug-in projects in a single project. Besides includeBuild can be configured to replace the Module relies on sub project of the use of more includeBuild please click access to gradle official document: docs.gradle.org/current/use…

Six, the last

If you think the article is good, or the RePluginX project can help you, just click on the free Star or Fork. That helps a lot. Thanks.

  • GitHub address: github.com/GitLqr/RePl…

If this article is helpful to you, please click on my wechat official number: FSA Full Stack Action, which will be the biggest incentive for me. The public account not only has Android technology, but also iOS, Python and other articles, which may have some skills you want to know about oh ~