【Android 插件化】Hook 插件化框架 ( Hook 技术 | 代理模式 | 静态代理 | 动态代理 )

简介: 【Android 插件化】Hook 插件化框架 ( Hook 技术 | 代理模式 | 静态代理 | 动态代理 )

文章目录

Android 插件化系列文章目录

前言

一、Hook 技术简介

二、代理机制

1、静态代理示例

2、动态代理示例

三、博客资源

前言

在之前的系列博客中 , 介绍了 " 插桩式 " 插件化框架 , 该框架存在一些问题 :


开发需要定制 : " 插件 " 模块中的 Activity 必须集成 BaseActivity , 其中很多操作都需要针对该方式进行 定制化开发 , 与开发普通的应用完全不同 ;


没有真正的上下文环境 : " 插件 " 模块内部 , 调用 Activity 组件的 getApplicationContext 方法会出现问题 , 因为 插件内部没有真正的供应用运行的上下文环境 ;


( 之前的 " 插桩式 " 插件化框架 , 只是简单示例 , 远远达不到能在项目中使用的复杂程度 )



插件化框架 的最终目的是让 " 插件 " 模块的开发和使用 , 与正常的应用开发和使用达到完全一致的效果 , " 宿主 " 模块 与 " 插件 " 模块 之间可以 无障碍通信 ;






一、Hook 技术简介


Hook 技术 又称为 钩子技术 , 同样 Hook 函数 也称为 钩子函数 ; 钩子技术 在 系统入侵 中 , 广泛使用 ;


Hook 技术 没有硬性规定技术标准 , 只是一种 技术概念 ; 在某一段代码的运行流程中 , 挂入自定义的钩子 , 在钩子的 前面 , 后面 , 可以 插入任意自定义的操作代码 , 达到 业务注入 的目的 ;



Hook 技术可以理解为 面向切面编程思想 , 想办法在不修改源码的前提下 , 在某个方法调用之前 , 插入自己的代码 , 业务逻辑 ,



Android 中的 Hook 技术 : 通过分析 Android 系统源码执行 , 通过 动态注入技术 , 在代码运行的某个阶段 , 注入开发者自定义的代码 ;



常用的动态注入技术 :


① 编译时修改字节码数据 : 代码编译时修改 Class 字节码数据 , 如 Dagger ;


② 运行时修改字节码数据 : 运行时可以修改字节码文件数据 , 达到代码入侵的效果 ;



Android 中的 Hook 机制 , 主要涉及到下面两种技术 :


① 反射机制 : Java 反射机制 ;


② 代理机制 : 动态代理 , 静态代理 ;






二、代理机制


代理机制 :


存在一个 目标对象 Subject 和 代理者 Proxy ;


目标对象 Subject 执行一些业务逻辑 , 代理者 Proxy 持有 目标对象 Subject , 当 目标对象 Subject 要执行某个方法时 , 通过 代理者 Proxy 调用 目标对象 Subject 中的方法执行 ;


代理者 Proxy 调用 目标对象 Subject 方法 之前 , 之后 , 可以插入自己的业务逻辑 ;



下面简要介绍 静态代理 与 动态代理 ;



1、静态代理示例


定义代理方法接口 : 代理者 和 目标对象 都要实现该接口 , 代理者 和 目标对象 可以进行相互替换 ;


/**
 * 代理者 和 目标对象 都要实现该接口
 * 代理者 可以替换 目标对象
 */
public interface AInterface {
    void request();
}



目标对象 : 被代理的目标对象 , 实现了


/**
 * 被代理的目标对象
 * 目标对象 Subject 执行一些业务逻辑
 * 代理者 Proxy 持有 目标对象 Subject
 * 当目标对象 Subject 要执行某个方法时
 * 通过 代理者 Proxy 调用 目标对象 Subject 中的方法执行
 */
public class Subject implements AInterface {
    /**
     * 目标对象的业务逻辑
     */
    @Override
    public void request() {
        System.out.println("Subject request");
    }
}



代理者 :


/**
 * 代理者
 * 目标对象 Subject 执行一些业务逻辑
 * 代理者 Proxy 持有 目标对象 Subject
 * 当目标对象 Subject 要执行某个方法时
 * 通过 代理者 Proxy 调用 目标对象 Subject 中的方法执行
 */
public class Proxy implements AInterface {
    /**
     * 代理者 持有的 目标对象
     */
    private Subject subject;
    public Proxy(Subject subject) {
        this.subject = subject;
    }
    /**
     * 当 Subject 需要执行 request 方法时 , 自己不直接执行
     * 而是通过 Proxy 的该方法调用 持有的 目标对象 Subject 来执行
     */
    @Override
    public void request() {
        before();
        subject.request();
        after();
    }
    /**
     * 执行 Subject 目标对象的 request 方法前执行的业务逻辑
     */
    private void before() {
        System.out.println("Proxy before");
    }
    /**
     * 执行 Subject 目标对象的 request 方法后执行的业务逻辑
     */
    private void after() {
        System.out.println("Proxy after");
    }
}



main 函数调用 : 通过代理者调用目标对象中的类 , 并在执行目标对象 Subject 的 request 方法时 , 对该方法进行逻辑增强 ;


① 方式一 :


public class Main {
    public static void main(String[] args) {
        // 1. 创建目标对象
        Subject subject = new Subject();
        // 2. 创建代理类
        Proxy proxy = new Proxy(subject);
        // 3. 通过代理类调用目标对象的方法
        proxy.request();
        /*
            代理类的作用 :
              执行 目标对象 Subject 的 request 方法时 ,
              对该方法进行逻辑增强 ;
         */
    }
}


② 方式二 :


public class Main {
    public static void main(String[] args) {
        /*
            下面的这种用法, 不需要关注目标对象
            只需要了解 Proxy 代理者
            调用者不了解目标对象的内部实现细节
            目标对象也不了解调用者
         */
        AInterface aInterface = new Proxy(new Subject());
        aInterface.request();
    }
}


执行结果 :


Proxy before
Subject request
Proxy after



2、动态代理示例


动态代理接口 :


/**
 * 代理者 需要实现的接口
 * 该接口就是动态代理接口
 */
public interface AInterface {
    void request();
}



目标对象 : 被代理的目标对象 , 需要实现代理接口 ;


public class Subject implements AInterface {
    @Override
    public void request() {
        System.out.println("Subject request");
    }
}


InvocationHandler 实现 : 这是 Hook 钩子 , 用于向被代理的目标对象的目标方法中注入业务逻辑 ;


import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;


public class AInvocationHandler implements InvocationHandler {


   /**

    * 被代理的对象

    */

   Object target;


   public AInvocationHandler(Object target) {

       this.target = target;

   }


   @Override

   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

       before();

       Object object = method.invoke(target, args);

       after();

       return object;

   }


   /**

    * 被代理对象方法调用之前执行

    */

   private void before(){

       System.out.println("AInvocationHandler before");

   }


   /**

    * 被代理对象方法调用之后执行

    */

   private void after(){

       System.out.println("AInvocationHandler after");

   }

}

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class AInvocationHandler implements InvocationHandler {
    /**
     * 被代理的对象
     */
    Object target;
    public AInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object object = method.invoke(target, args);
        after();
        return object;
    }
    /**
     * 被代理对象方法调用之前执行
     */
    private void before(){
        System.out.println("AInvocationHandler before");
    }
    /**
     * 被代理对象方法调用之后执行
     */
    private void after(){
        System.out.println("AInvocationHandler after");
    }
}


动态代理执行 main 函数 :


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Main {
    public static void main(String[] args) {
        // 1. 创建目标对象
        Subject subject = new Subject();
        // 2. 获取目标对象类加载器
        ClassLoader classLoader = subject.getClass().getClassLoader();
        // 3. 获取接口 Class 数组, Subject 只实现了一个 AInterface 接口
        Class<?>[] interfaces = subject.getClass().getInterfaces();
        // 4. 创建 InvocationHandler , 传入被代理的目标对象 , 处理该目标对象中被代理的函数
        InvocationHandler invocationHandler = new AInvocationHandler(subject);
        // 5. 动态代理 :
        //    ① jdk 根据传入的参数信息 , 在内存中动态的创建 与 .class 字节码文件等同的字节码数据
        //    ② 将字节码数据 转为 对应的 字节码类型
        //    ③ 使用反射调用 newInstance 创建动态代理实例
        AInterface proxy = (AInterface) Proxy.newProxyInstance(
                classLoader,
                interfaces,
                invocationHandler);
        // 正式调用被动态代理的类
        proxy.request();
    }
}



执行结果 :


AInvocationHandler before
Subject request
AInvocationHandler after





三、博客资源


博客资源 :


GitHub :




目录
相关文章
|
3月前
|
安全 Android开发 iOS开发
安卓与iOS的较量:技术深度对比
【10月更文挑战第18天】 在智能手机操作系统领域,安卓和iOS无疑是两大巨头。本文将深入探讨这两种系统的技术特点、优势以及它们之间的主要差异,帮助读者更好地理解这两个平台的独特之处。
66 0
|
2月前
|
安全 搜索推荐 Android开发
揭秘安卓与iOS系统的差异:技术深度对比
【10月更文挑战第27天】 本文深入探讨了安卓(Android)与iOS两大移动操作系统的技术特点和用户体验差异。通过对比两者的系统架构、应用生态、用户界面、安全性等方面,揭示了为何这两种系统能够在市场中各占一席之地,并为用户提供不同的选择。文章旨在为读者提供一个全面的视角,理解两种系统的优势与局限,从而更好地根据自己的需求做出选择。
135 2
|
2月前
|
安全 搜索推荐 Android开发
揭秘iOS与安卓系统的差异:一场技术与哲学的较量
在智能手机的世界里,iOS和Android无疑是两大巨头,它们不仅定义了操作系统的标准,也深刻影响了全球数亿用户的日常生活。本文旨在探讨这两个平台在设计理念、用户体验、生态系统及安全性等方面的本质区别,揭示它们背后的技术哲学和市场策略。通过对比分析,我们将发现,选择iOS或Android,不仅仅是选择一个操作系统,更是选择了一种生活方式和技术信仰。
|
3月前
|
安全 Android开发 iOS开发
iOS与安卓:技术生态的双雄争霸
在当今数字化时代,智能手机操作系统的竞争愈发激烈。iOS和安卓作为两大主流平台,各自拥有独特的技术优势和市场地位。本文将从技术架构、用户体验、安全性以及开发者支持四个方面,深入探讨iOS与安卓之间的差异,并分析它们如何塑造了今天的移动技术生态。无论是追求极致体验的苹果用户,还是享受开放自由的安卓粉丝,了解这两大系统的内在逻辑对于把握未来趋势至关重要。
|
3月前
|
安全 搜索推荐 Android开发
揭秘iOS与Android系统的差异:一场技术与哲学的较量
在当今数字化时代,智能手机操作系统的选择成为了用户个性化表达和技术偏好的重要标志。iOS和Android,作为市场上两大主流操作系统,它们之间的竞争不仅仅是技术的比拼,更是设计理念、用户体验和生态系统构建的全面较量。本文将深入探讨iOS与Android在系统架构、应用生态、用户界面及安全性等方面的本质区别,揭示这两种系统背后的哲学思想和市场策略,帮助读者更全面地理解两者的优劣,从而做出更适合自己的选择。
|
2月前
|
搜索推荐 安全 Android开发
安卓与iOS的哲学对话:技术生态中的选择与命运
【10月更文挑战第24天】 在智能设备的世界里,安卓和iOS不仅是操作系统的简单对立,它们代表了不同的技术哲学和生态策略。本文将探讨这两种系统背后的设计理念、用户体验差异以及它们如何塑造我们的数字生活,从而引发对于“我们如何选择技术”这一命题的深入思考。
|
2月前
|
安全 5G Android开发
安卓与iOS的较量:技术深度解析
【10月更文挑战第24天】 在移动操作系统领域,安卓和iOS无疑是两大巨头。本文将深入探讨这两个系统的技术特点、优势和不足,以及它们在未来可能的发展方向。我们将通过对比分析,帮助读者更好地理解这两个系统的本质和内涵,从而引发对移动操作系统未来发展的深思。
58 0
|
2月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
1月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
55 19
|
1月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
60 14