长截屏原理
前几天看到小米手机的长截屏功能,几天下来有了如下思路。
1. 找到到目标Activity实例
2. 控制目标Activity实例滑动截屏
3. 传递截屏数据到当前进程
A)首先如何找到目标Activity实例。
先看下图:
对于每个Activity实例,其所在的进程有唯一的ActivityThread实例(PS:其main方法其实是应用入口)。ActivityThread中有ApplicationThread用于进程间通信。每个Activity实例在当前进程用ActivityClientRecord保存状态。
而AMS(即ActivityManagerService)所在的SS(即SystemServer)进程中,有对应的ProcessRecord实例对应,其内部变量IApplicationThread thread用于跟应用进程通信,Activity实例在SS的描述为ActivityRecord。
从上面描述可知,可以先从AMS获取对应的ActivityRecord(),然后找到ProcessRecord,通过其内部变量IApplicationThread thread跟目标进程的ActivityThread通信,为了方便可以通过AMS将IApplicationThread 传递过来。
修改如下:
1. 在ActivityManagerService继承的接口IActivityManager中添加新方法,用于获取目标Activity的IApplicationThread
B)接下来是控制目标Activity实例滑动截屏
修改如下:
1. 在IApplicationThread 中添加方法,用于控制Activity滑动
2. 当滑动满一屏或者截止时drawbitmap
C)最后是传递图片到当前进程
考虑用binder传送,但是一次传送可能过大,可分多次传送。
D)以上两个修改了IActivityManager和IApplicationThread 。为了接口简单考虑,可改为添加两个新的IXXX。
以下两个位置是相关修改位置:
ActivityManagerService中的setSystemProcess
ActivityThread中的attach方法用传递IApplicationThread 到SS进程。