Target和Retention注解
这两个注解是元注解(meta-annotation)用来定义自己的注解接口时用,@Target定义注解用于什么地方,比如是用于方法还是用于类型。Retention用于定义注解在哪个级别可用,在源代码(Source),在类中(Class),还是在运行时(Runtime), 另外两个java原生支持的元注解是@Documented(将注解包含在Javadoc)和 @Interited(允许子类继承父类中的注解)
还有三种标准注解: @Override, @Deprecated @Suppress Warnings
依赖注入
solopi使用自定义的Subscriber/Provider注解,在injectorService依赖注入管理服务中将事件连接起来,通过Subscriber的参数来区分。
录制Case的流程
入口点从NewRecordActivity看起。 initAppHeadView中设置startRecord按钮的功能。在检查权限之后,调用startRecord(caseInfo)。
这个方法调用CaseRecordManager里面的 setRecordCase, 这个函数设置一下case的一些参数,然后把目标app调用起来。而CaseRecordManager可以在onCreate的时候最后绑定到FloatWinService. 这个Serivce 的oncreate-> createView中会创建悬浮的录制控制栏(页面 float_win). 并调用WindowsManager将录制控制栏设置为前端的悬浮窗口。
在createView中,对record设置ClickListener,当点击时调用runListener.onRunClick。而这个listener时CaseRecordManager里面bind服务的时候传入的RecordFloatConnection中设置的。
在FloatClickListener中定义了onRunClick, 先隐藏悬浮窗口,然后开始记录。
OperationService并不是一个安卓的服务,是自定义的一个带有辅助工具性质的类,用来做一些用户操作步骤的管理
OperationStepService也是用于辅助功能,对用户的操作做一些辅助的逻辑。他的processer是在NewRecordActivity中注册的,注册为OperationLogHandler. 这个Handler用于存放用户的操作步骤,存放在一个优先级队列中。
OperationStepExporter用于对于操作步骤进行处理,转换成OperationStep,包括进行辅助节点的查找,尺寸信息的记录等。
startTrackAccessibilityEvent检查Accessibility是否开启,如果没有开启的话发送Intent Settings.ACTION_ACCESSIBILITY_SETTINGS进行启用。如果已经开启。则设置新的AccessibilityEventTracker,设置其Listener为一个EventProxy实例。startTrackTouch看起来似乎跟startTrackAccessibilityEvent做类似的事情,因为都把listener设置为了 proxy。
TouchEventTracker和AccessibiityEventTracker的区别和联系后续再分析
然后,setServiceToTouchBlockMode设置截断用户输入。
当AccessibilityServiceImpl被初始化的时候,会触发Provider信号,从而调用AccessibilityEventTracker中的setAccessibilityService方法。把自身注册给AccessibilityServiceImpl的Listener,来响应Accessibility事件。当收到Accessbility或Gesture信号之后,调用notifyAccessibilityEvent或notifyGestureEvent 。
Notify之后,EventProxy中发出信号,ResponseTools中接收事件,记录在RecordList中。
TouchEventTracker在开启后,会启动一个命令“adb shell getevent -lt”,这个命令会持续地列出手机上的输入事件(这个方法可能也适用于其他Linux系统, 比如去cat /dev/input下面的设备信号),如果侦测到点击操作,会调用NotifyTouchStart等一些函数。当EVENT_TOUCH_POSITION信号发出时,CaseRecordManager中的receiveTouchPosition会被调用。如果点到了soloPi的图标,用showFunctionView显示默认的菜单,否则显示被点中的node元素的相关菜单。
我理解TouchEventTracker主要是为了考虑到需要支持游戏或者网页这种没有Accessibility节点树的场景,对于有节点树的情况,为什么不直接用Accessbility事件来侦测触摸事件呢?
显示操作菜单
showFunctionView如果不带参数,构建默认菜单。带参数的话,构建节点相关的菜单,并调用highlight。这里可以看一下对于图形树的处理,是显示一个窗口并让用户自己拖拽控制截图区域的。
构建keys和icons之后,FunctionSelectUtil.showFunctionView创建菜单(实际调用DialogUtils.showLeveledFunctionView)。并设置菜单点击后的回调 processAction。
DialogUtils.showLeveledFunctionView
新建一个TwoLevelSelectLayout(这是个LinearLayout)。然后设置菜单,用AlertDialog显示出来。
processAction
processAction根据Action的类型,处理后执行operationAndRecord
弱引用
在A中创建对于B的弱引用,可以避免A无法被GC,防止内存泄漏。参考:
https://www.cnblogs.com/CVstyle/p/6395745.html
//TODO
ScheduledExecutorService
Executors.newSingleThreadScheduledExecutor
WakeLock
PriorityQueue
AsyncTask
自定义的AccessibilityService进行Gesture模拟
dispatchGesture只能在android 24(安卓O)以上版本使用。需要添加 android:canPerformGestures="true" 的meta-data
https://stackoverflow.com/questions/44420320/perform-swipe-on-screen-using-accessibilityservice
AtomicInteger
因为i++, i-- 之类的操作不是线程安全的,所以为了应对高并发情况下的数据准确性,设计了这个类。参考:
https://blog.csdn.net/fanrenxiang/article/details/80623884
同样,c#中的++操作也不是线程安全的。
https://stackoverflow.com/questions/4628243/is-the-operator-thread-safe
不过同样注意,不要用AtomicInteger任意代替integer, 它没有equals,hashCode和CompareTo,原子类中也没有byte等类别。参考:
https://developer.android.com/reference/java/util/concurrent/atomic/package-summary.html
Parcelable
parcelable用于序列化,不过比Serializable效率更高。不过如果要序列化到本地文件,还是推荐用Serializable。
参考;
https://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html
用重用布局元素
用
https://developer.android.com/training/improving-layouts/reusing-layouts