replugin-plugin-gradle:
作用:是一个Gradle插件,由插件负责引入,主要负责在插件的编译期中:配置插件打包相关信息;动态替换插件工程中的继承基类。
1.ReClassPlugin
作用:继承于Plugin<Project>,实现了apply方法。
2.PluginDebugge(命令功能类)
作用:基于adb shell + am 命令,实现 发送广播,push apk 等功能
代码:
public boolean startHostApp() {
if (isConfigNull()) {
return false
}
String cmd = "${adbFile.absolutePath} shell am start -n \"${config.hostApplicationId}/${config.hostAppLauncherActivity}\" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER"
if (0 != CmdUtil.syncExecute(cmd)) {
return false
}
return true
}
3.def assembleTask(根Task)
作用:获取assemble task(即打包apk的task),后续的task需要依赖此task,比如安装插件的task,肯定要等到assemble task打包生成apk后,才能去执行。
4.installPluginTask.doLast(安装Task)
作用:依赖于assemble task,任务内容为启动宿主 -> 卸载插件 -> 强制停止宿主 -> 启动宿主 -> 安装插件。
5.Transfrom
Transform 是 Android Gradle API ,允许第三方插件在class文件转为dex文件前操作编译完成的class文件,这个API的引入是为了简化class文件的自定义操作而无需对Task进行处理。
实现方法:实现一个继承自Transform的自定义 Transform 类。
通过registerTransform(@NonNull Transform transform, Object... dependencies)注册自 定义 Transform 类。
6.includedInjectors()(注入器集合方法)
作用:返回用户未忽略的注入器的集合:
(1)LoaderActivityInjector 替换插件中的Activity的继承相关代码 为 replugin-plugin-library 中的XXPluginActivity父类
(2)LocalBroadcastInjector 替换插件中的LocalBroadcastManager调用代码 为 插件库的调用代码。
(3)ProviderInjector 替换 插件中的 ContentResolver 调用代码 为 插件库的调用代码
(4)ProviderInjector2 替换 插件中的 ContentProviderClient 调用代码 为 插件库的调用代码
(5)GetIdentifierInjector 替换 插件中的 Resource.getIdentifier 调用代码的参数 为 动态适配的参数
7.LoaderActivirtyInjector(Activity注入器)
作用:用来修改插件中XXActivity类中的顶级XXActivity父类 为 XXPluginActivity父类。
其init()指定了 Activity 替换规则,只替换那些顶级Activity父类为 replugin-plugin-lib 库中的 XXPluginActivity。
def private static loaderActivityRules = [
'android.app.Activity' : 'com.qihoo360.replugin.loader.a.PluginActivity',
'android.app.TabActivity' : 'com.qihoo360.replugin.loader.a.PluginTabActivity',
'android.app.ListActivity' : 'com.qihoo360.replugin.loader.a.PluginListActivity',
'android.app.ActivityGroup': 'com.qihoo360.replugin.loader.a.PluginActivityGroup',
'android.support.v4.app.FragmentActivity' : 'com.qihoo360.replugin.loader.a.PluginFragmentActivity',
'android.support.v7.app.AppCompatActivity': 'com.qihoo360.replugin.loader.a.PluginAppCompatActivity',
'android.preference.PreferenceActivity' : 'com.qihoo360.replugin.loader.a.PluginPreferenceActivity',
'android.app.ExpandableListActivity': 'com.qihoo360.replugin.loader.a.PluginExpandableListActivity'
]
8.LocalBroadcastInjector(广播注入器)
作用:实现了替换插件中的LocalBroadcastManager的方法调用为插件库的PluginLocalBroadcastManager中的方法调用。
def injectClass(ClassPool pool, String dir, Map config) {
...
try {
// 不处理 LocalBroadcastManager.class
if (filePath.contains('android/support/v4/content/LocalBroadcastManager')) {
println "Ignore ${filePath}"
return super.visitFile(file, attrs)
}
stream = new FileInputStream(filePath)
ctCls = pool.makeClass(stream);
// println ctCls.name
if (ctCls.isFrozen()) {
ctCls.defrost()
}
/* 检查方法列表 */
ctCls.getDeclaredMethods().each {
it.instrument(editor)
}
ctCls.getMethods().each {
it.instrument(editor)
}
ctCls.writeFile(dir)
}
...
}
(filePath.contains('android/support/v4/content/LocalBroadcastManager'):避免替换掉v4包中的源码实现。
9.ProviderInjector(ContentResolver注入器)
作用:主要用来替换插件中的ContentResolver相关的方法调用为插件库的PluginProviderClient中的对应方法调用。
public static def includeMethodCall = ['query',
'getType',
'insert',
'bulkInsert',
'delete',
'update',
'openInputStream',
'openOutputStream',
'openFileDescriptor',
'registerContentObserver',
'acquireContentProviderClient',
'notifyChange',
]
10.ProviderInjector2(内容注入器)
作用:主要用来替换插件中的ContentProviderClient相关的方法调用。
public static def includeMethodCall = ['query', 'update']
static def includeMethodCall中定义了需要处理的目标方法名
public class ProviderExprEditor2 extends ExprEditor {
static def PROVIDER_CLASS = 'com.qihoo360.loader2.mgr.PluginProviderClient2'
@Override
void edit(MethodCall m) throws CannotCompileException {
...
replaceStatement(m, methodName, m.lineNumber)
...
}
def private replaceStatement(MethodCall methodCall, String method, def line) {
methodCall.replace('{$_ = ' + PROVIDER_CLASS + '.' + method + '(com.qihoo360.replugin.RePlugin.getPluginContext(), $$);}')
println ">>> Replace: ${filePath} Provider.${method}():${line}"
}
}
PROVIDER_CLASS指定了对应的替代实现类
replaceStatement(...)中,替换方法体:
替换query和update:
replace statement:'{$_ = ' + PROVIDER_CLASS + '.' + method + '(com.qihoo360.replugin.RePlugin.getPluginContext(), $$);}'
11.GetIdentifierInjector(动态参数注入器)
作用:主要用来替换插件中的Resource.getIdentifier方法调用的参数为动态适配的参数。
public class GetIdentifierExprEditor extends ExprEditor {
public def filePath
@Override
void edit(MethodCall m) throws CannotCompileException {
String clsName = m.getClassName()
String methodName = m.getMethodName()
if (clsName.equalsIgnoreCase('android.content.res.Resources')) {
if (methodName == 'getIdentifier') {
m.replace('{ $3 = \"' + CommonData.appPackage + '\"; ' +
'$_ = $proceed($$);' +
' }')
println " GetIdentifierCall => " +'{ $3 = \"' + CommonData.appPackage + '\"; ' +
'$_ = $proceed($$);' +
' }'
println " \n";
println " GetIdentifierCall => ${filePath} ${methodName}():${m.lineNumber}"
}
}
}
}
edit( )中,遍历到调用方为android.content.res.Resources且方法为getIdentifier的MethodCall,动态适配这些MethodCall中的方法参数。