The introduction

In the last article, we studied the ClassLoader scheme design in hot repair, which is mainly used to load plug-ins.

Having seen how hosts load different plug-ins, let’s take a look at how plug-in programming is implemented, and how one of the famous Tencent teams (PS: said to be a business group of Tencent Video, etc.) uses plug-in to achieve dynamic design

The plugin programming

A flowchart

1) Plug-in project development is actually an APP project to realize plug-in business

2) During the development process, the plug-in needs to be constantly debugged to check whether the host load and use is normal. Then, the plug-in needs to be frequently copied to the place where the host can use it (such as: asset, etc.), which can be implemented with scripts

3) Host validation

Above is a brief overview of the process. Next, let’s look at the details and simple implementation of each process.

The plug-in project

Here is an APP module, which is mainly to realize the plug-in’s own business, such as: Cool Dog APP, there are modules such as listening to songs/live broadcast, each module is actually a plug-in APK

Plug-in related scripts

After the plugin function is developed, the plugin APK needs to be copied to the host project or other places for the host to load and use. This process involves the automation of scripts, such as the script of Shadow’s sample-Manager plugin APK (note that the following scripts are implemented in the host gradle file) :

1) In the gradle file of the host, the copy time of the plug-in is mounted in the build process of the host. This is convenient in the development process.

tasks.whenTaskAdded { task ->
    if (task.name == "generateDebugAssets") {
        generateAssets(task, 'debug')
    }
    if (task.name == "generateReleaseAssets") {
        generateAssets(task, 'release')
    }
}
Copy the code

2) Implementation of generateAssets:

/*** * 1)generateAssetsTask, system task anchor * 2)buildType, debug/release * */ def generateAssets(generateAssetsTask, buildType) { println "daviAndroid generateAssets" def moduleName = 'sample-manager' def pluginManagerApkFile = file("${project(":sample-manager").getBuildDir()}" + "/outputs/apk/${buildType}/" + "${moduleName}-${buildType}.apk") / / createCopyTask hung on in the generateAssetsTask, system task of anchor point "in the front of the generateAssetsTask. DependsOn createCopyTask (' : sample - the manager, buildType, moduleName, 'pluginmanager.apk', pluginManagerApkFile, "assemble${buildType.capitalize()}" ) }Copy the code

3) createCopyTask implementation:

// Add module apK (e.g. Sample copies - manager) to the project build/generated/assets/xx/def createCopyTask (projectName buildType, name, apkName, inputFile, taskName) { println "daviAndroid createCopyTask" def outputFile = file("${getBuildDir()}/generated/assets/${name}/${buildType}/${apkName}") outputFile.getParentFile().mkdirs() return tasks.create("copy${buildType.capitalize()}${name.capitalize()}Task", Copy) {group = 'build' description = "Copy ${name} into assets." from(inputfile.getparent ()) {include(inputfile.name) rename { outputFile.name } } into(outputFile.getParent()) }.dependsOn("${projectName}:${taskName}") }Copy the code

PS1: pay attention to this copy to the host of “build/generated/assets/xx/”, in the host read openAsset way, so the project need to be configured to assets

 sourceSets {
        debug {
            assets.srcDir('build/generated/assets/sample-manager/debug/')
        }
        release {
            assets.srcDir('build/generated/assets/sample-manager/release/')
        }
    }
Copy the code

PS2: PS2

validation

Above has completed the plug-in development, plug-in copy; The following is the host in the copy of the directory to load and use, about the loading method of the section has different ways, you can choose according to their own business needs, the specific code here >>

Plug-in to achieve dynamic design

background

We all know that a feature of Tencent’s Shadow framework is full dynamic design. The code of the plug-in framework (such as the configuration and upgrade of the plug-in) has become a part of the plug-in, and the implementation of iteration is no longer limited by the host packaging the old version of the plug-in framework

The configuration upgrade of the plug-in is implemented dynamically

Plug-in in the iterative process, there will be different business under the use of different plug-ins, so here it is necessary to achieve plug-in download/update logic;

Normally this logic is written in the host, but Shadow makes this logic dynamic through the plugin’s thinking, so that subsequent strategies are not confused when they need to be adjusted

Let’s take a look at how shadow is implemented, and explain the process according to the code, the code location is here >>

The implementation process

1) Design idea

A) Host: load the interface implementation in the plug-in in the way of interface dependence to realize the dynamic of the plug-in

B) Interface: Joe connects the host and plug-in

C) Plug-in: download plug-in services, preload other plug-ins, etc

If the download service or preload logic needs to be changed, you only need to change the implementation of the plug-in and deliver it again

2) Plug-in module

Here is the engineering architecture:

A) About constant, some constants

B) About dynamic-manager

The implementation mechanism of cross-process Service, plug-in loading and other services are based on such IPC scheme as the bearer

C) About manager

Plug-in load/update/download specific implementation classes, such as: load plug-in type/plug-in bean/ plug-in ZIP configuration description, etc

D) About dynamic-host

The first thing to note is that this module is only available to the plug-in at compile time, and then not to the plug-in, and the host public module

The main modules are public modules used by the host and the plug-in, such as the custom ApkClassLoader, which the host needs to load the plug-in, and the Sample-Manager plug-in manager, which needs to load other plug-ins

3) Host module

Here is the engineering architecture:

1) About app

Host startup module, involving the trigger plug-in update timing/plug-in copy to local, etc

2) About constant, some constants (and the plugin public module, see the plugin section above)

3) About dynamic-host

The main functions are described in the plugins section above, but the difference is that the module is plugged into the host

4) About Commons-io

File IO related libraries

At the end

Haha, that’s all for this article (systematic learning and growing together)

Tips

For more exciting content, please follow “DaviAndroid” wechat public account