天天看点

【Android】Android动态代理为SurfaceHolder添加Hook代理模式镜像翻转源码分析代理实现源码下载

本博客将会介绍动态代理在android应用中的一种使用场景

代理模式的作用是为其它对象提供一种代理以控制对这个对象的访问。比如用户调用了一个“吃饭”的方法,如果不依靠代理,用户可能自己拿碗饭吃就行,而如果通过代理的话,可能连碗都不需要用户自己拿,用户只需要张开嘴,代理来喂就行了,需要注意的是,这里代理除了负责拿碗和喂饭外还可以做其他的任何事情,比如说帮你把饭吹凉一些,或者担心你的体重而偷偷帮你倒掉了一半的饭,又或者是往饭里加点什么奇奇怪怪的东西,谁知道呢,这就是代理干的活。实际上在java里面也提供了代理这一神奇的模式,而且还分为静态和动态两种,两者的区别是静态代理的结构在程序运行前就已经安排好了的,而动态代理则是在程序运行过程中指定的,本文所采用的就是动态代理方法。

【Android】Android动态代理为SurfaceHolder添加Hook代理模式镜像翻转源码分析代理实现源码下载
【Android】Android动态代理为SurfaceHolder添加Hook代理模式镜像翻转源码分析代理实现源码下载

镜像水平翻转前后效果

对于一般的view而言,直接用view.setscaley(-1)即可达到这样的效果,而且针对自定义surfaceview,也可以使用

来进行翻转。但是如果面对的是第三方surfaceview,且无法直接获取到surfaceview用于绘制的canvas对象的话。比如上面左图实现代码如下。

假设testsurfaceview在第三方jar包中,且无法对其进行修改。那么该如何对这个界面进行镜像翻转呢,下面给出通过动态代理实现的方案

结合上面的代码,我们知道,surfaceview的绘制过程如下:

【Android】Android动态代理为SurfaceHolder添加Hook代理模式镜像翻转源码分析代理实现源码下载

surfaceview绘制流程

通常调用代码如下:

holder是什么呢,我们可以在surfaceview的源码里找到surfaceholder的实例msurfaceholder以及实现。

在源码里,我们可以看到msurfaceholder里实现了lockcanvas方法,并且返回了canvas,这里就是突破口。

代理的目标是要实现对surfaceholder里的lockcanvas方法进行监控,并为其返回值添加一定的操作,也就是将原先的流程改为如下结构:

【Android】Android动态代理为SurfaceHolder添加Hook代理模式镜像翻转源码分析代理实现源码下载

动态代理添加访问控制

首先需要实现的是代理处理器,其代码如下:

代理处理器做的是在invoke的地方将lockcanvas方法过滤了出来,然后执行lockcanvas方法,并获返回值,这个返回值就是canvas对象,这个canvas是surfaceview将要在上面作画的画布,所以这里我们可以通过代理事先为其添加镜像翻转的效果,添加完成之后之后返回给正常流程来继续执行。

完成代理处理器之后就可以为surfaceholder添加动态代理,这里需要注意的是surfaceholder在surfaceview中,所需先取出来,再为之添加代理,代码如下:

新生成的newsurfaceholder就是已经添加上动态代理的surfaceholder,因为在surfaceview中surfaceholder是私有属性,无法直接替换,所以这里需要借助反射机制来讲newsurfaceholder替换掉surfaceview中原先的msurfaceholder,代码如下:

添加动态代理之后,testsurfaceview中调用holder的lockcanvas方法所获取到的canvas都是经过testinvocation转置的canvas,从而实现了这个奇怪的需求,也就是实现右侧图片的效果。

整个工程的源码如下

<a target="_blank" href="https://github.com/obobear/proxysurfaceview">android动态代理实践</a>

继续阅读