接入腾讯Shadow插件化框架
一.源码地址
文档:
其实官方文档说的已经很清楚了,建议反复阅读
官方文档,才能对后面的接入有更好的理解.
二.体验demo
三.接入到项目
3.1首先将插件库发布的本地仓库中,方便后续依赖
在`buildScripts/gradle/maven.gradle`文件中配置了Shadow的Maven发布脚本。
正式使用时,请修改其中的两个GroupID变量:`coreGroupId`、`dynamicGroupId`,
以及`setScm`方法中的两个URL到自己的版本库地址上。
然后将`mavenLocal()`改为自己发布的目标Maven仓库。
执行`./gradlew publish`即可将Shadow SDK发布到Maven仓库。
官方已经为你配置好了maven发布脚本,可以改也可以不改,不改的话执行
./gradlew publish
成功后,在下面目录可找到文件:
/Users/.m2/repository/com/tencent/shadow/dynamic
/Users/.m2/repository/com/tencent/shadow/core
3.2 用Android Studio 分别打开
projects/sample/maven/host-project
,projects/sample/maven/manager-project
,projects/sample/maven/plugin-project
三个目录。
其中host-project是宿主工程,manager-project是插件管理功能,plugin-project是插件项目.
注意这三个工程每一个都是一个单独的工程,都有各自的作用,接下来我们要做的就是分别仿照
这三个工程的接入方式,进行配置
3.3 配置你自己的宿主工程
添加本地仓库
mavenLocal()
添加依赖
implementation project(':introduce-shadow-lib')
implementation "com.tencent.shadow.dynamic:host:$shadow_version"
Application中初始化
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
InitApplication.*onApplicationCreate*(this);
}
}
清单文件中注册服务,以及插件容器Activity(其实这些已经在introduce-shadow-lib为我们做好了)
,但是我们不妨留意一下,因为这里配置了插件的服务进程,以及插件的容器页面
<service
android:name=".MainPluginProcessService"
android:process=":plugin" />
```
<!--container 注册
注意configChanges需要全注册
theme需要注册成透明
这些类不打包在host中,打包在runtime中,以便减少宿主方法数增量
-->
<activity
android:name="com.tencent.shadow.sample.runtime.PluginDefaultProxyActivity"
android:launchMode="standard"
android:screenOrientation="portrait"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
android:hardwareAccelerated="true"
android:theme="@style/PluginContainerActivity"
android:process=":plugin" />
<activity
android:name="com.tencent.shadow.sample.runtime.PluginSingleInstance1ProxyActivity"
android:launchMode="singleInstance"
android:screenOrientation="portrait"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
android:hardwareAccelerated="true"
android:theme="@style/PluginContainerActivity"
android:process=":plugin" />
<activity
android:name="com.tencent.shadow.sample.runtime.PluginSingleTask1ProxyActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
android:hardwareAccelerated="true"
android:theme="@style/PluginContainerActivity"
android:process=":plugin" />
<provider
android:authorities="com.tencent.shadow.contentprovider.authority.dynamic"
android:name="com.tencent.shadow.core.runtime.container.PluginContainerContentProvider" />
宿主启动插件Activity
public static final int *FROM_ID_START_ACTIVITY* = 1001;
PluginManager pluginManager = InitApplication.*getPluginManager*();
pluginManager.enter(MainActivity.this, *FROM_ID_START_ACTIVITY*, new Bundle(), new EnterCallback() {
@Override
public void onShowLoadingView(View view) {
MainActivity.this.setContentView(view);//显示Manager传来的Loading页面
}
@Override
public void onCloseLoadingView() {
MainActivity.this.setContentView(linearLayout);
}
@Override
public void onEnterComplete() {
v.setEnabled(true);
}
});
这是一个接口方法,在manager工程中有对应的实现
@Override
public void enter(final Context context, long fromId, Bundle bundle, final EnterCallback callback) {
if (fromId == Constant.*FROM_ID_START_ACTIVITY*) {
bundle.putString(Constant.*KEY_PLUGIN_ZIP_PATH*, "/data/local/tmp/plugin-debug.zip");
bundle.putString(Constant.*KEY_PLUGIN_PART_KEY*, "sample-plugin");
bundle.putString(Constant.*KEY_ACTIVITY_CLASSNAME*, "com.tencent.shadow.sample.plugin.MainActivity");
onStartActivity(context, bundle, callback);
} else if (fromId == Constant.*FROM_ID_CALL_SERVICE*) {
callPluginService(context);
} else {
throw new IllegalArgumentException("不认识的fromId==" fromId);
}
}
可以看到 bundle.putString(Constant.KEY_ACTIVITY_CLASSNAME,"com.tencent.shadow.sample.plugin.MainActivity"
);传入了插件工程中的Activity
混淆配置
-keep class com.tencent.shadow.core.common.**{*;}
-keep class com.tencent.shadow.core.runtime.**{*;}
-keep class com.tencent.shadow.dynamic.host.**{*;}
3.4 配置你自己的插件管理工程manager-project
暂时原封不动的按照README的提示,进行打包,
./gradlew assembleDebug
并手动push到data/local/temp文件夹下(模拟下载过程)
adb push sample-manager/build/outputs/apk/debug/sample-manager-debug.apk /data/local/tmp
3.5 配置你自己的插件工程plugin-project
你可以像平时开发普通项目一样开发插件功能,但是要在插件工程项目,添加两个依赖包sample-loader
和sample-runtime
app目录中的build.gradle添加依赖:
//Shadow Transform后业务代码会有一部分实际引用runtime中的类
//如果不以compileOnly方式依赖,会导致其他Transform或者Proguard找不到这些类
compileOnly "com.tencent.shadow.core:runtime:$shadow_version"
并在最下面添加如下配置
shadow {
packagePlugin {
pluginTypes {
debug {
loaderApkConfig = new Tuple2('sample-loader-debug.apk', ':sample-loader:assembleDebug')
runtimeApkConfig = new Tuple2('sample-runtime-debug.apk', ':sample-runtime:assembleDebug')
pluginApks {
pluginApk1 {
businessName = 'sample-plugin'//businessName相同的插件,context获取的Dir是相同的。businessName留空,表示和宿主相同业务,直接使用宿主的Dir。
partKey = 'sample-plugin'
buildTask = 'assemblePluginDebug'
apkName = 'plugin-app-plugin-debug.apk'
apkPath = 'plugin-app/build/outputs/apk/plugin/debug/plugin-app-plugin-debug.apk'
}
}
}
release {
loaderApkConfig = new Tuple2('sample-loader-release.apk', ':sample-loader:assembleRelease')
runtimeApkConfig = new Tuple2('sample-runtime-release.apk', ':sample-runtime:assembleRelease')
pluginApks {
pluginApk1 {
businessName = 'demo'
partKey = 'sample-plugin'
buildTask = 'assemblePluginRelease'
apkName = 'plugin-app-plugin-release.apk'
apkPath = 'plugin-app/build/outputs/apk/plugin/release/plugin-app-plugin-release.apk'
}
}
}
}
loaderApkProjectPath = 'sample-loader'
runtimeApkProjectPath = 'sample-runtime'
version = 4
compactVersion = [1, 2, 3]
uuidNickName = "1.1.5"
}
}
混淆配置
#kotlin一般性配置 START
-dontwarn kotlin.**
-keepclassmembers class **$WhenMappings {
<fields>;
}
-keepclassmembers class kotlin.Metadata {
public <methods>;
}
#kotlin一般性配置 END
#kotlin优化性能 START
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
}
#kotlin优化性能 END
-keep class org.slf4j.**{*;}
-dontwarn org.slf4j.impl.**
-keep class com.tencent.shadow.dynamic.host.**{*;}
-keep class com.tencent.shadow.dynamic.impl.**{*;}
-keep class com.tencent.shadow.dynamic.loader.**{*;}
-keep class com.tencent.shadow.core.common.**{*;}
-keep class com.tencent.shadow.core.loader.**{*;}
-keep class com.tencent.shadow.core.runtime.**{*;}
-dontwarn com.tencent.shadow.dynamic.host.**
-dontwarn com.tencent.shadow.dynamic.impl.**
-dontwarn com.tencent.shadow.dynamic.loader.**
-dontwarn com.tencent.shadow.core.common.**
-dontwarn com.tencent.shadow.core.loader.**
命令行运行,编译插件
./gradlew packageDebugPlugin
并push到data/local/tmp(模拟下载过程)
adb push build/plugin-debug.zip /data/local/tmp
至此所有配置操作完毕,可以即刻感受Shadow框架带给插件化开发的便利,这只是一个简单接入的一个小demo,是Shadow插件功能的冰山一角,它还有很多强大的功能,比如还有多插件发布,插件更新,插件使用宿主类等功能,可以等熟练使用了之后慢慢体会
注意事项
3.3,3.4,3.5
分别对应三个不同的工程不要搞到一个工程,各自有各自的作用
AGP7.0以上引入Gradle插件可以暂时这样配置
buildscript {
repositories {
谷歌()
mavenCentral()
mavenLocal()
}
dependencies {
classpath "com.tencent.shadow.core:gradle-plugin:local--SNAPSHOT"
}
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgahhea
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01