(2)Android插件化编程思想

本篇博客是学习《Android插件化开发指南》的一个总结

1. 插件化的优势

a> 快速修复应用中的bug,不需要重新发版本

b> 快速响应需求,能够将应用业务的变化动态的发布给用户

其实以上的两个优点也可以总结成一个,就是用户重新不要重新下载安装APK,就可以更新APK的功能。

2. 插件化编程需要了解和掌握的知识

   a>对Android的框架知识需要有一定的了解。因为在编写应用 的过程中我们可以需要在应用运行的过程中在原生的逻辑之上增加我们自己的逻辑,或者绕过Android原生的某些限制,所以就需要我们对Android内置的系统服务有一定的了解,才能更好的实现我们想要的逻辑,其中比较重要的就是AMS,PMS,WMS以及与这三个相关的类和方法,

   b>Android四大组件的运行原理也必须要清楚。

   c> java反射技术。反射是java自身的技术和Android没有关系,但是Android是基于java开发的,那么我们就可以利用反射这一技术实现我们想要的功能。在插件化编程中,针对某些对象和方法的原生的实现逻辑,但是有些对象在Android内置的类中是私有的,正常的情况下我们是没有办法获取到的,此时就需要利用反射的方法,来获取这些私有的变量,修改他们的逻辑。

   d>java的类加载机制也必须要清楚,不仅是理论上的,需要能够结合实际的需求去使用。在插件化编程中,原生的APP中的对象和方法想要调用插件APP中的对象和方法,必须要借助类加载器将插件中的对象和方法加载到虚拟机中。所以针对插件APK中的对象和方法到底应该以什么样的方式进行加载就是一个值得考虑的问题。

   e>代理模式。代理模式也是一个在插件化编程中必须要用到的方法,代理又分为静态代理和动态代理,动态代理就需要用到反射的方法。采用静态代理需要为每一个被代理的对象配置一个代理类,如果被代理的对象很多的话,就会增加很多的代码,使用项目编程臃肿;动态代理可以一个代理类代理多个对象 ,增加了代码的复用,减少代码量。代理模式的目的主要也是为了灵活的控制被代理对象的行为,在插件化编程时主要的作用是在Android原生的逻辑之上,增加我们自己想要的逻辑,这一方式通常称为Hook,就是用我们自己写的对象,替换Android中原本的对象。即用我们自己的对象代理了原生的对象。

3.插件化编程具体的实现

   在应用插件化的时候我们主要需要解决以下的问题:

    a>对Android四大组件的插件化

    针对应用开发来讲最重要的就是Android的四大组件(Activity,Service,Provider,Broadcast),这四者几乎构成了一个APK的全部。以下我们分别总结针对四大组件的插件化.

   Activity:对于Activity的插件化,我们需要解决以下几个问题:

    (1)宿主App中的Activity如何启动插件App中的Activity

       我们都知道想要在启动任何的四大组件,都必须要在Manifest文件中声明,如果启动一个没有在Manifest中声明的Activity就会报错。为什么会报错呢,因为AMS在启动一个Activity的时候会去检查该Activity是否被定义在Manifest中,如果不在就会报Activity Not Found的异常。因为我们的插件是后来才加的,一开始宿主App也不会知道我们要启动什么Activity,所以插件中的Activity是不会定义在Manifest文件中,此时如果我们想要启动插件中的Activity,

       需要解决两个问题

       1)要能够加载我们所启动的Activity

       在Java中类的加载是通过ClassLoader进行加载的,每一个Apk最后都会被系统编译成对应的dex文件,应用的启动都依赖以 相应的ClassLoader对Class的加载,有两种ClassLoader  (a)PathClassLoader (b)DexClassLoader。PathClassLoader只能加载已经安装到系统的APK,而DexClassLoader则主要用来加载jar,apk,dex文件,针对我们的插件APK,想要运行,就可以利用DexClassLoader将其加载到系统中。我们需要new一个 DexClassLoader对象并传递插件APK的路径。

       2)需要让AMS认为插件中的Activity是定义在Manifest中。

      如何让AMS认为插件中的Activity是在Mainfest中定义过的呢,因为AMS会去检查我们要启动的Activity是否在Manifest中定义,如果我们能够绕过检查点,就可以,怎么做呢,我们事先在Manifest中定义几个空的Activity ,当我们想要启动插件的Activity的时候,我们先启动预定的那些Activity,等过AMS 的检查点之后,再将预定义的Activity替换回插件中的Activity。

      通过查看Android系统的源码,发现其实Activity的实例化就是利用反射的方法生成Activity对象,所以在启动的插件Activity的时候,我们也需要利用反射的方法生成插件中的Activity对象,在反射的时候需要传递ClassLoader对象,那么此时的ClassLoader就需要传递我们new出来的DexClassLoader. 因为宿主APP的ClassLoader是不知道插件APP中的类的信息的,只有根据插件app的信息生成的插件的DexClassLoader才能够加载插件的类。

     思路就是这样一种思路,具体要在什么地方替换,就是具体的实现问题了。

    (2)插件中的Activity如何启动宿主App中的Activity

        插件中的Activity启动宿主App中的Activity应该没有什么特别的,按照我们通常方法调用就可以

      (3)   插件中Activity的启动模式的处理

        采用插件方式启动的插件Activity只能使用标准模式启动,所以如果想支持SingleTop,SingleInstance,SingleTask就必须我们自己来手动实现。书中说的方法是通过占位的方式,预先在宿主App中设置好对应的启动类型的Activity,然后将我们的Activity和预先设置好的Activity对应起来,当我们启动插件中的Activity的时候,先找到插件Activity对应的在宿主App中预设的Activity进行启动,在启动的过程中宿主中预设的Activity是有启动模式的,所以我们插件中的Activity,也就有启动模式了。

   Service:对于Service

    (1)如何启动宿主中的插件中的Service,与Activity不同的是Activity可以有多个实例对象,而Service只有一个实例对象

       针对Service的插件化需要我们针对插件中的每一个Service在宿主app中预先放置一个预制的Service,因为对同一个 service多次启动只会有一个Service实例。所以我们的插件中的Service必须和预制的Service一一对应。思路和Acitivity的插件化是一样的通过欺骗AMS进行。在AMS中我们将我们要启动的Service替换为之前预定义的Service,而真正要启动service的时候,再换回我们要启动的Service

      (2)   Service的生命周期函数的调用

      bindService unBindService

    Provider和Broadcast的生命周期比较简单,所以处理上没有Activity和Service那么繁琐。

b>对资源的插件化

 针对资源访问,最大的一个问题就是插件App中的资源ID有可能和宿主App中的资源ID产生冲突,应用不知道该找哪一个资源。

   (1)合并dex文件,修改插件资源的前缀,以区别于宿主App中的资源的Id

   (2)不和并的话,为每一个 插件生成各自的AssetManager,访问插件的资源用插件的AssetManager,访问宿主的AssetManager用宿主的AssetManager

4.其他一些相关的技术

a>针对Fragment的插件化

b>Activity和HTML之间的相互调用

c>插件的混淆

d>增量更新

e>对so文件的插件化

f>APK打包流程的Hook

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值