Android插件化开发-hook动态代理

首先,我们阐述为什么android需要插件化:
1:由于业务的增长,app的方法数逐渐达到65535(有人说用于检索方法数的列表大小使用short存储的,其实我看了源码之后并没有发现相关信息,并对此说法产生了怀疑,不过最后找到的结果就是,65535这个限制可能是由于dalvik的bytecode大小限制的,具体的可以查看官方文档)。
2:一个模块的变化都要整体编译一次app,维护成本太大了,用插件开发app会好很多

对于以上问题解决方案不少,著名的有h5,hybird,不过这些都没有native的体验好,于是之后又有react-native。不过本文不是阐述react-native,所以这里不加阐述。

国内也跟进,360推出了DroidPlugin*git*

我也开始学习他的这个项目,所以才有本文。也很感激网上有很多前辈已经贴出相关的文章,可供我参考借鉴

关于代理技术的话,熟悉spring的读者应该非常熟悉,spring利用动态代理实现AOP,极大的方便了开发

我们举个例子。如果,老板欠了我们的工资不发,我们是需要通过法律途径解决的,不过,我们大多数人应该不是自己去诉讼,而是请一位律师,这位律师就好比一个代理,帮助我们完成整个诉讼流程,我们自己只需在一旁只认老板罪行就行

我们定义一个接口,里面有各种诉讼流程

/**
 * Created by chan on 16/4/10.
 */
public interface ILawsuit {
   
   
    /**
     * 提交诉讼
     */
    void submit();

    /**
     * 举证
     */
    void burden();

    /**
     * 辩护
     */
    void defend();

    /**
     * 结束
     */
    void finish();
}

我们的代表-小明,决定站起来做这个诉讼人

/**
 * Created by chan on 16/4/10.
 */
public class XiaoMing implements ILawsuit {
   
   

    @Override
    public void submit() {
        System.out.println("老板拖欠工资");
    }

    @Override
    public void burden() {
        System.out.print("合同书在这里,这是我的工资流水");
    }

    @Override
    public void defend() {
        System.out.println("证据都在这里  别BB");
    }

    @Override
    public void finish() {
        System.out.println("诉讼成功");
    }
}

律师:


/**
 * Created by chan on 16/4/10.
 */
public class Lawyer implements ILawsuit {
   
   
    private ILawsuit m_iLawsuit;

    public Lawyer(ILawsuit iLawsuit) {
        m_iLawsuit = iLawsuit;
    }

    @Override
    public void submit() {
        System.out.println("拟仲裁材料");
        m_iLawsuit.submit();
    }

    @Override
    public void burden() {
        System.out.println("指导委托人准备的材料");
        m_iLawsuit.burden();
    }

    @Override
    public void defend() {
        System.out.println("争取到委托人辩护的机会");

        //委托人开始辩护
        m_iLawsuit.defend();
    }

    @Override
    public void finish() {
        System.out.println("交涉");
        //显然证据确凿 肯定成功
        m_iLawsuit.finish();
    }
}

我们看到律师在委托人做具体事情之前,已经为其铺好垫,他只需简单的履行自己的职责,而无需关注外部环境发生了什么。

理解了代理是什么,我们开始真正的开始了
细想一下之前的例子,我们不难得出,在android里面如果我们需要Hook的话,这个hookd点要容易找到,小明毕竟是个具体的人,他是个代表嘛。自然我们hook时,应当针对单例的对象,或者静态的对象,因为他们只有一份,且相对不会发生改变。

好像有点抽象,我们还是举个例子吧。比如,我们现在要在每次启动一个activity之前都要打印一条信息。
最笨的方式就是用一个BaseActivity集成Activity,但是,如果我们这个项目已经进行了N多年,想象一下,这得修改多少源码,且这破坏了我们的设计原则,我们尽量扩展而不是修改代码。那些已有的代码都是经历时间考验的,修改之后可靠性会下降。

那么我们就HOOK吧。 先查看源码找一找线索
当我们启动一个Activity的时候,肯定都会调用startActivity**之类的代码

比如:

startActivity(intent);

我们切进去看下:


    /**
     * Same as {@link #startActivity(Intent, Bundle)} with no options
     * specified.
     *
     * @param intent The intent to start.
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see {@link #startActivity(Intent, Bundle)}
     * @see #startActivityForResult
     */
    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

它调用了activity的 startActivity(Intent, Bundle)

再跟踪:

 @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

又调用了startActivityForResult(Intent intent, int requestCode)

public void startActivityForResult(Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

又调用了startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options)

/**
     * Launch an activity for which you would like a result when it finished.
     * When this activity exits, your
     * onActivityResult() method will be called with the given requestCode.
     * Using a negative requestCode is the same as calling
     * {
  
  @li
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值