在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:WandFix开源软件地址:https://gitee.com/miqt/WandFix开源软件介绍:WandFix本项目旨在实现像web开发一样开发Android,代码写好发布之后就能让用户立即看到,而不是必须每次打包apk -> 更新 -> 安装,实现方式是Activity和资源文件的动态替换。 2019年12月27日14:58:43 本项目替换了热修复的方式,由之前的反射替换类的方式,改为了使用Hack Classloader mParent的方式。 众所周知,在android中正常情况下有两个ClassLoader,分别是,BootCLassLoader - PathClassLoader 当加载一个类的时候,基于双亲委托,先由BootCLassLoader 加载这个类,如果BootCLassLoader不存在,则由PathClassLoader加载这个类。 而本项目的核心替换方法就是,在BootCLassLoader - PathClassLoader 中间,插入了一个自定义的WandClassLoader,这样,当我们的项目加载一个类的时候,会先试用WandCLassLoader 加载,我们就达到替换的目的了,相对于替换之前,达到了无使用反射的目的。 AboutWandFix是一个可以使用注解来注入实现类对象的库,基于java APT+反射+classloader,因此不需要使用new来初始化对象。另外它还可以动态加载指定.apk .dex .jar .class文件,使用注入设置优先级的方式来选择注入class类的来源,因此利用此种方法,该项目还可以使得被注解的类获得热修复的能力! 使用 WandFix 只需要对变量名添加注解即可实现对象的注入。而热修复功能的实现既是用对象注入的这种途径,通过更换热修复包替换实现类,来达到每次注入的对象都为最后改动过的,实现热修复的目的。当然,如果您不想使用热修复功能,只是想方便的注入对象,直接添加注解也是可以的,因为如果它在热修复包中没有找到对应的实现类的话,会尝试从项目本地来加载对应的类,保证程序的稳定。 本项目Demo效果预览:(2019年4月12日17:23:29 更新: 针对使用这个项目进行实际的项目开发,我还写了一个简单的项目,它或许是使用本项目开发的一个比较好的示例。传送门) 优点:
使用方法:在项目根目录的build.gradle添加: allprojects { repositories { ... maven { url 'https://jitpack.io' } }} 然后在:app:添加依赖: annotationProcessor 'com.github.miqt.WandFix:wand-compiler:v1.3.6'compile 'com.github.miqt.WandFix:wand:v1.3.6' 实现activity动态代理activity动态代理就是把一个activity的全部事情,都交给一个代理类去处理,而这个代理本质上也是一个类,一个对象,因此我们只要使用DexClassloader一替换,即变成了动态代理。 先新建一个activity,继承ProxyActivity,然后添加 //绑定代理类@BindProxy(clazz = TextActivityProxy.class)//必须继承 ProxyActivitypublic class TextActivity extends ProxyActivity { //这里什么都不用写} 然后新建一个class 继承 ActivityProxy 实现代理方法 //每个代理类都要设置@AddToFixPatchpublic class TextActivityProxy extends ActivityProxy { public TextActivityProxy(ProxyActivity acty) { super(acty); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { mActy.setContentView(R.layout.activity_hello); ... } ...} 直接 实现单个类文件的热修复public class MainActivity extends AppCompatActivity implements Wand.MotorListener { @InjectObject( //指向类的全名 value = "com.miqt.demo.presenter.AppPresenterImpl", //设置双亲委托 //项目开发中建议使用PROJECT,优先应用本地类库。 //项目发布时,应修改为NEVER,优先应用热修复包中的类库。 level = ParentalEntrustmentLevel.NEVER) AppPresenter ap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //可以在application中初始化一次即可 Wand.get().init(this).listener(this); } public void getStr(View view) { //使用注解注入对象必须要调用这一行 ClassInstall.inject(this); //或者带参数的构造方法 //Map<String, Object[]> pramHouse=new HashMap<>(); //pramHouse.put("com.miqt.demo.presenter.AppPresenterImpl",new Object[]{"hello"}); //ClassInstall.inject(this,pramHouse); //也可以不使用注解注入的方式初始化对象 //ap= ObjectFactory.make("com.miqt.demo.presenter.AppPresenterImpl"/*,构造参数*/); //ap= ObjectFactory.make(AppPresenterImpl.class/*,构造参数*/); String str = ap.getStr(); Toast.makeText(this, str, Toast.LENGTH_SHORT).show(); }} 加载apk插件中的资源文件 //先根据apk插件文件路径创建PluginResources //需要文件读写权限才行 PluginResources manager = new PluginResources(context, pluginApkPath); //颜色资源加载 int id=manager.getId("text_color", "color"); int color = manager.getResources().getColor(id, context.getTheme()); textView.setTextColor(color); //布局加载 View main_layout=manager.getLayout("activity_main"); 相关注解用法及作用说明
代码混淆相关如果项目设置了混淆,需要将以下代码复制到混淆配置文件中: -keep class com.miqt.wand.**{*;}-keep class * {@com.miqt.wand.anno.InjectObject <fields>;}-keep @com.miqt.wand.anno.AddToFixPatch class * {*;}-keep @com.miqt.wand.anno.BindProxy class * {*;} Other千里之行,始于足下,欢迎提出问题和宝贵意见。 具体更多用法请移步Wiki 如果您觉得这个项目还不错,就点个star吧( ̄▽ ̄)~* 开发中遇到的问题和现存问题
|
请发表评论