Android 模拟点击

Android 模拟点击功能

  1. 使用adb命令

通过adb shell命令是下面的格式:

adb shell input tap 520 1024 //点击(520,1024)
adb shell input swipe 200 200 300 300 //滑动(200,200)到(300,300)

直接使用 ProcessBuilder 执行shell命令

                //利用ProcessBuilder执行shell命令
                String[] order = {
                        "input",
                        "tap",
                        "520",
                        "720"
                };
                try {
                    new ProcessBuilder(order).start();
               } catch (IOException e) {
                    e.printStackTrace();
               }

特别注意点
此方法只在自己应用内有效
例如在自己的activity中,你会看到点击或者滚动效果,用处不大是吧,自己的应用,想模拟点击,或者滚动,我直接调用定义的方法就好,哪还需要什么模拟点击或者手势呢

  1. 辅助功能AccessibilityService
    AccessibilityService非常强大,模拟点击,滑动,不论什么应用,自己的应用、桌面、系统的应用都是可以的
    AccessibilityService是一个service,需要在Android manifest文件中注册,其次需要配置自己的辅助功服务(注册、配置)
    配置的方式:
  • 可以在manifest中通过xml方式配置meta-data
<?xml version="1.0" encoding="utf-8"?>
<!--accessibilityEventTypes 监视的动作-->
<!--accessibilityFeedbackType提供反馈类型,语音震动等等。-->
<!--accessibilityFlags监视的view的状态,注意这里设置flagDefault会到时候部分界面状态改变,不触发onAccessibilityEvent(AccessibilityEvent event)的回调
|flagRetrieveInteractiveWindows|flagIncludeNotImportantViews|flagReportViewIds|flagRequestTouchExplorationMode-->
<!--canRetrieveWindowContent是否要能够检索活动窗口的内容,此设置不能在运行时改变-->
<!--description功能描述-->
<!--notificationTimeout同一事件间隔时间名-->
<!--    android:packageNames="com.android.gallery3d,com.android.mediacenter,com.android.recorder,com.android.providers.media,com.android.systemui"-->
<!--packageNames监控的软件包名-->
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
   android:accessibilityEventTypes="typeAllMask"
   android:accessibilityFeedbackType="feedbackAllMask"
   android:accessibilityFlags="flagDefault|flagReportViewIds"
   android:canRetrieveWindowContent="true"
   android:canPerformGestures="true"
   android:description="我是辅助功能"
   android:canRequestEnhancedWebAccessibility=""
   android:canRequestFilterKeyEvents=""
   android:canRequestTouchExplorationMode=""
   android:packageNames=""
   android:settingsActivity=""
   android:summary=""
   android:notificationTimeout="100" />
        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"
            android:label="我是辅助功能"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>

            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/accessibility_service_config" />
        </service>

  • 通过辅助功能类的onServiceConnected()中初始化

@Override
protected void onServiceConnected() {
   super.onServiceConnected();
   AccessibilityServiceInfo info = new AccessibilityServiceInfo();
   info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
   info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
   info.notificationTimeout = 100;
   info.packageNames = new String[]{"...", "..."};
   info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
   setServiceInfo(info);
}

在onServiceConnected代码块中,配置属性有限,但灵活的在服务里边初始化,使我们可以随时的改变需要的flag和type及一些其他参数。而xml的meta-data的配置方式,可配置的属性更多。在系统条件符合时(同时不需要更改我们辅助功能的一些参数时),还是推荐使用xml方式进行辅助功能的配置。

XML attributes:

AccessibilityEventTypes 此服务希望接收的事件类型

constant value 描述
typeAllMask ffffffff 所有类型的事件
typeAnnouncement 4000 一个应用产生一个通知事件
typeAssistReadingContext 1000000 辅助用户读取当前屏幕事件
typeContextClicked 800000 view中上下文点击事件
typeGestureDetectionEnd 80000 监测到的手势事件完成
typeGestureDetectionStart 40000 开始手势监测事件
typeNotificationStateChanged 40 收到notification弹出消息事件
typeTouchExplorationGestureEnd 400 触摸浏览事件完成
typeTouchExplorationGestureStart 200 触摸浏览事件开始
typeTouchInteractionEnd 200000 用户触屏事件结束
typeTouchInteractionStart 100000 触摸屏幕事件开始
typeViewAccessibilityFocusCleared 10000 无障碍焦点事件清除
typeViewAccessibilityFocused 8000 获得无障碍的焦点事件
typeViewClicked 1 点击事件
typeViewFocused 8 view获取到焦点事件
typeViewHoverEnter 80 一个view的悬停事件
typeViewHoverExit 100 一个view的悬停事件结束,悬停离开该view
typeViewLongClicked 2 view的长按事件
typeViewScrolled 1000 view的滚动事件,adapterview、scrollview
typeViewSelected 4 view选中,一般是具有选中属性的view,例如adapter
typeViewTextChanged 10 edittext中文字发生改变的事件
typeViewTextSelectionChanged 2000 edittext文字选中发生改变事件
typeViewTextTraversedAtMovementGranularity 20000 UIanimator中在一个视图文本中进行遍历会产生这个事件,多个粒度遍历文本。一般用于语音阅读context
typeWindowContentChanged 800 窗口的内容发生变化,或者更具体的子树根布局变化事件
typeWindowStateChanged 20 新的弹出层导致的窗口变化(dialog、menu、popupwindow)
typeWindowsChanged 400000 屏幕上的窗口变化事件,需要API 21+

accessibilityFeedbackType 此服务提供的反馈类型

constant value 描述
feedbackAllMask ffffffff 取消所有的可用反馈方式
feedbackAudible 4 可听见的(非语音反馈)
feedbackGeneric 10 通用反馈
feedbackHaptic 2 触觉反馈(震动)
feedbackSpoken 1 语音反馈
feedbackVisual 8 视觉反馈

accessibilityFlags 辅助功能附加的标志,多个使用 |分割

constant value 描述
flagDefault 1 默认的配置
flagEnableAccessibilityVolume 80 这个标志要求系统内所有的音频通道,使用由STREAM_ACCESSIBILTY音量控制USAGE_ASSISTANCE_ACCESSIBILITY
flagIncludeNotImportantViews 2 表示可获取到一些被表示为辅助功能无权获取到的view
flagReportViewIds 10 使用该flag表示可获取到view的ID
flagRequestAccessibilityButton 100 如果辅助功能可用,提供一个辅助功能按钮在系统的导航栏 API 26+
flagRequestEnhancedWebAccessibility 8 此类扩展的目的是为WebView中呈现的内容提供更好的辅助功能支持。这种扩展的一个例子是从一个安全的来源注入JavaScript。如果至少有一个具有此标志的辅助功能服务, 则系统将使能增强的web辅助功能。因此, 清除此标志并不保证该设备不会使能增强的web辅助功能, 因为可能有另一个使能的服务在使用它。
flagRequestFilterKeyEvents 20 能够监听到系统的物理按键
flagRequestFingerprintGestures 200 监听系统的指纹手势 API 26+
flagRequestTouchExplorationMode 4 系统进入触控探索模式。出现一个鼠标在用户的界面
flagRetrieveInteractiveWindows 40 该标志知识的辅助服务要访问所有交互式窗口内容的系统,这个标志没有被设置时,服务不会收到TYPE_WINDOWS_CHANGE事件。

canRequestEnhancedWebAccessibility (boolean)
辅助功能服务是否能够请求WEB辅助增强的属性。例如: 安装脚本以使应用程序内容更易于访问。

canRequestFilterKeyEvents (boolean)
辅助功能服务是否能够请求过滤KeyEvent的属性,是否可以请求KeyEvent事件流。,flagRequestFilterKeyEvents搭配使用

canRequestTouchExplorationMode (boolean)
此属性用于,能够让辅助功能服务通过手势,来请求触摸浏览模式,其被触摸的项,将被朗读出来,flagRequestTouchExplorationMode搭配使用

canRetrieveWindowContent (boolean)
辅助功能服务是否能够取回活动窗口内容的属性。 与上边的flagRetrieveInteractiveWindows搭配使用,无法在运行时更改此设置。

description
辅助功能服务目的或行为的简短描述。

notificationTimeout
同一类型的两个辅助功能事件发送到服务的最短间隔(毫秒,两个辅助功能事件之间的最小周期)

packageNames
从此服务能接收到事件的软件包名称 (不适合所有软件包)(多个软件包用逗号分隔)。

settingsActivity
允许用户修改辅助功能的activity组件名称

summary
同description

AccessibilityService类的public方法

Method 描述
API 20 以前
getRootInActiveWindow() 获取窗体中的节点信息。 返回 AccessibilityNodeInfo,如果需要使用该方法,我们需要在配置中申明 canRetrieveWindowContent,否则可能获取不到窗体的节点信息AccessibilityNodeInfo
getServiceInfo() 获取本服务的配置信息。 返回 AccessibilityServiceInfo
getSystemService(String name) 通过服务名获取对应的系统服务。 返回 Object
onAccessibilityEvent(AccessibilityEvent event) 辅助功能事件(s)回调方法,处理辅助功能内所有事件的回调方法
onBind(Intent intent) service的bind接口
onInterrupt() 辅助功能中断的回调
performGlobalAction(int action) 全局的点击方法
setServiceInfo(AccessibilityServiceInfo info) 设置该辅助功能服务的描述,修改辅助功能的配置。可通过搭配使用getServiceInfo()动态修改我们辅助功能的配置
API 21新增:
getWindows() 返回窗口最上层的一个用户可交互的窗口信息节点 List<AccessibilityWindowInfo>
API 24新增:
disableSelf() 关闭自己service的方法,在设置界面可以看到辅助功能状态被关闭
getSoftKeyboardController() 返回软键盘控制器AccessibilityService.SoftKeyboardController,可用于查询和修改软键盘显示模式。添加addOnShowModeChangedListener()的方式来进行对键盘的显示隐藏状态监听,通过getShowMode()获取到软键盘的显示隐藏状态,setShowMode(int showMode)设置软键盘的显示隐藏状态。
findFocus(int focus) 找到具有指定焦点类型的视图。搜索在所有窗口中执行。注意:为了访问Windows,您的服务必须通过在其元数据中设置AccessibilityService_canRetrieveWindowContent属性来声明检索窗口内容的功能。有关详细信息,请参阅SERVICE_META_DATA。此外,服务必须选择通过设置FLAG_RETRIEVE_INTERACTIVE_WINDOWS标志来检索交互式窗口。否则,搜索将仅在活动窗口中执行。这里的焦点类型有FOCUS_INPUT和FOCUS_ACCESSIBILITY分别代表了输入焦点和无障碍重点。FOCUS_ACCESSIBILITY这个焦点,是需要使用setAccessibilityFocused(boolean isFocus)方法进行设置过得焦点。
getMagnificationController() 返回放大控制器,可用于查询和修改显示放大的状态。注意:为了控制放大倍数,您的服务必须通过在其元数据中设置AccessibilityService_canControlMagnification属性来声明该功能
dispatchGesture(GestureDescription ge, GestureResultCallback cb, Handler handler) 将手势发送到触摸屏。目前正在进行的任何手势(无论是从用户,本服务还是其他服务)将被取消。 手势将被调度,就像在用户直接在屏幕上执行的一样,因此事件可能会受到诸如放大和触摸探索之类的功能的影响。通过设定GestureDescription将手势的轨迹显示在触摸屏上,同时可以通过GestureResultCallback回调获得事件的完成情况
API 26新增:
getAccessibilityButtonController() 返回系统导航区域中可访问性按钮的控制器AccessibilityButtonController。当设置FLAG_REQUEST_ACCESSIBILITY_BUTTON时,此实例可用于查询辅助功能按钮的状态并注册监听器以进行交互和辅助功能按钮的状态更改。当设置FLAG_REQUEST_ACCESSIBILITY_BUTTON时,此类可用于查询辅助功能按钮的状态并注册回调以进行交互,并对可访问性按钮进行状态更改。注意:此类和FLAG_REQUEST_ACCESSIBILITY_BUTTON不应该被用作通过AccessibilityService为用户提供功能的唯一手段。 一些设备实现可以选择不提供软件呈现的系统导航区域,使得该功能永久不可用。注意:在支持辅助功能按钮的设备实现中,它可能始终不可用,例如前台应用程序使用SYSTEM_UI_FLAG_HIDE_NAVIGATION时。 用户还可以选择将该按钮分配给另一个可访问性服务或功能。 在每种情况下,将调用注册的AccessibilityButtonController.AccessibilityButtonCallback的onAvailabilityChanged(AccessibilityButtonController,boolean)方法来提供对可访问性按钮对注册服务的可用性的更改的通知。
getFingerprintGestureController() 获取控制器的指纹手势。此功能需要 AccessibilityServiceInfo#CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES。注意:在调用此方法之前,必须先启动该服务。返回 FingerprintGestureController。只要设备具有能够检测手势的传感器,AccessibilityService可以捕获在设备的指纹传感器上执行的手势。使用时需要声明CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES同时需要权限USE_FINGERPRINT

主要使用的方法是:
getRootInActiveWindow()	//获取窗体中的节点信息 AccessibilityNodeInfo,如果需要使用该方法,我们需要在配置中申明 canRetrieveWindowContent,否则可能获取不到窗体的节点信息。AccessibilityNodeInfo
onAccessibilityEvent(AccessibilityEvent event)	//辅助功能事件(s)回调方法,处理辅助功能内所有事件的回调方法
performGlobalAction(int action)	//全局的点击方法,包括home按键、返回按键、任务键、电源键

AccessibilityEvent的公有方法:

Method 描述
appendRecord(AccessibilityRecord record) 将AccessibilityRecord追加到事件记录的结尾。
getRecord(int index) 获取给定索引下的记录。
getRecordCount() 获取被包含在事件中的记录数。
describeContents() 描述被包含在 Parcelable 实例的编组表示中的特殊对象种类。例如,如果对象在 writeToParcel(Parcel, int)的输出里包括一个文件描述符,该方法的返回值必须包括 CONTENTS_FILE_DESCRIPTOR 位。
getEventType() 获取事件类型。
setEventType(int eventType) 设置事件类型。
eventTypeToString(int eventType) 返回一个事件类型的字符串表示。例如,TYPE_VIEW_CLICKED 的字符串表示为“TYPE_VIEW_CLICKED”。
getAction() 获取触发该事件的执行操作。
getContentChangeTypes() 获取由 TYPE_WINDOW_CONTENT_CHANGED 事件标识的改变类型的位掩码。一个单一事件可能代表多种变化类型。
getEventTime() 获取该事件的发送时间。
setEventTime(long eventTime) 设置事件被发送的时间。
getMovementGranularity() 获取遍历的移动粒度。
setMovementGranularity(int granularity) 设置遍历的移动粒度。
getPackageName() 获取源的包名。
setPackageName(CharSequence packageName) 设置源的包名。
initFromParcel(Parcel parcel) 从 Parcel 创建一个新实例。
obtain(AccessibilityEvent event) 如果可获得,返回一个缓存实例或创建一个新实例。返回实例从给定事件初始化。
obtain() 如果可获得,返回一个缓存实例或实例化一个新的。
obtain(int eventType) 如果可获得,返回一个缓存实例或实例化一个新的并设置它的类型属性。
recycle() 回收一个实例重复使用。
setAction(int action) 设置触发此事件的执行操作。
setContentChangeTypes(int changeTypes) 设置由一个 TYPE_WINDOW_CONTENT_CHANGED 事件标识的节点树改变的位掩码。
toString() 返回对象的字符串表示。一般情况下,toString 方法返回一个“文本表示”该对象的字符串。结果应该是一个简洁但容易阅读的信息表示。建议所有子类重写该方法。
writeToParcel(Parcel parcel, int flags) 整组该对象到一个 Parcel。

AccessibilityNodeInfo

nodeInfo.performAction(int action)performAction(int action, Bundle bundle)方法

action常量:

Action 释义
ACTION_ACCESSIBILITY_FOCUS 给节点添加无障碍焦点的操作。
ACTION_ARGUMENT_COLUMN_INT 让指定集合列在屏幕上可见的参数。
ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 当以一定粒度移动时,是否扩大选择范围或反之移除的参数。
ACTION_ARGUMENT_HTML_ELEMENT_STRING 要移动到的下一个/上一个 HTML 元素的参数。
ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 当遍历节点文本的时,使用哪种移动粒度的参数。。
ACTION_ARGUMENT_PROGRESS_VALUE 指定要设置的进度值的参数。
ACTION_ARGUMENT_ROW_INT 让指定集合行在屏幕上可见的参数。
ACTION_ARGUMENT_SELECTION_END_INT 指定选择结束的参数。
ACTION_ARGUMENT_SELECTION_START_INT 指定选择起始的参数。
ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE 指定要设置的文本内容的参数。
ACTION_CLEAR_ACCESSIBILITY_FOCUS 清除节点无障碍焦点的操作。
ACTION_CLEAR_FOCUS 清除节点输入焦点的操作。
ACTION_CLEAR_SELECTION 取消选择节点的操作。
ACTION_NEXT_AT_MOVEMENT_GRANULARITY 以给定移动粒度,请求去到该节点文本的下一个文本实体的操作。
ACTION_CLICK 在节点信息上点击的操作.
ACTION_COLLAPSE 折叠一个可展开节点的操作。
ACTION_COPY 将当前选择拷贝到剪贴板的操作。
ACTION_CUT 剪贴当前选项并放置到剪贴板的操作。
ACTION_DISMISS 关闭一个可关闭节点的操作。
ACTION_EXPAND 展开一个可展开节点的操作。
ACTION_FOCUS 给节点添加输入焦点的操作。
ACTION_LONG_CLICK 在节点上点击长按的操作。
ACTION_NEXT_HTML_ELEMENT 移动到给定类型的下一个 HTML 元素的操作。例如,移动到 BUTTON、INPUT、TABLE 等。
ACTION_PASTE 粘贴当前剪贴板内容的操作。
ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY 以给定移动粒度,请求去到该节点文本的上一个文本实体的操作。例如,移动到下一个字、词等。
ACTION_PREVIOUS_HTML_ELEMENT 移动到给定类型的上一个 HTML 元素的操作。例如,移动到BUTTON、INPUT、TABLE 等。
ACTION_SCROLL_BACKWARD 向后滚动节点内容的操作。
ACTION_SCROLL_FORWARD 向前滚动节点内容的操作
ACTION_SELECT 选择节点的操作。
ACTION_SET_SELECTION 设置选择项的操作。执行该操作,并且无参数清除选项
ACTION_SET_TEXT 设置节点文本的操作。在没有参数的情况下执行该操作,使用 null 或者空CharSequence 将会清除文本。该操作也将会把光标放置到文本末尾
FOCUS_ACCESSIBILITY 无障碍焦点。
FOCUS_INPUT 输入焦点。
MOVEMENT_GRANULARITY_CHARACTER 以字符为移动粒度位,遍历节点文本
MOVEMENT_GRANULARITY_LINE 以行为移动粒度位,遍历节点文本。
MOVEMENT_GRANULARITY_PAGE 以页为移动粒度位,遍历节点文本。
MOVEMENT_GRANULARITY_PARAGRAPH 以段为移动粒度位,遍历节点文本。
MOVEMENT_GRANULARITY_WORD 以字词为移动粒度位,遍历节点文本。

AccessibilityNodeInfo的方法
Public Method 释义
addAction(int action) 为一个nodeInfo添加一个操作,在API 21时被弃用
addAction(AccessibilityNodeInfo.AccessibilityAction action) 为一个nodeInfo添加一个操作,API 21
addChild(View root, int virtualDescendantId) 添加一个虚拟子元素,作为给定根节点的子view
addChild(View child) 添加一个子view节点。
canOpenPopup() 获取该节点是否可以打开一个弹窗或对话框。
describeContents() 描述被包含在可打包实例的封装代表中的特殊对象的种类。
equals(Object object) 标识是否有某些其他对象“等同于”该对象。
findAccessibilityNodeInfosByText(String text) 使用文本找到 AccessibilityNodeInfo。
findAccessibilityNodeInfosByViewId(String viewId) 使用完全合格视图id的源名称找到AccessibilityNodeInfo,完全合格 id 的样式 如下“package:id/id_resource_name”。
findFocus(int focus) 找到具有指定焦点类型的视图。
focusSearch(int direction) 在指定方向搜索具有输入焦点的最近的视图。
getActionList() 获取可以在该节点上执行的操作。
getActions() 该方法在 API 级别 21 被弃用。使用getActionList()代替。
getBoundsInParent(Rect outBounds) 获取父级坐标中的节点边界。
getBoundsInScreen(Rect outBounds) 获取屏幕坐标中的节点边界。
getChild(int index) 获取给定索引下的子元素。
getChildCount() 获取子元素的数目。
getClassName() 获取该节点来自的类。
getCollectionInfo() 如果节点是个集合,获取集合信息。一个集合子集总是一个集合项目。
getCollectionItemInfo() 如果节点是个集合项目,获取集合项目信息。一个集合项目总是一个集合的子集。
getContentDescription() 获取该节点的内容描述。
getExtras() 获取具有附加数据的可选 bundle。该包是闲时创建的且永不为 null。注意:为了避免冲突,推荐使用应用的包名作为关键字字首,如果从不同应用发出的相同关键词有不同的含义,可能会导致无障碍服务困扰。
getInputType() 获取定义为 InputType 的源中的输入类型。
getLabelFor() 为无障碍目的,获取作为标签代表该视图的节点信息。 返回AccessibilityNodeInfo
getLabeledBy() 为无障碍目的,获取作为标签代表该视图的节点信息。返回AccessibilityNodeInfo
getLiveRegion() 获取该节点的实时区域模式。一个实时区域是一个包含对用户来说重要信息的节点,且当其改变时应该告知用户。例如,在一个登录界面,有一个呈现“密码错误”通知的 TextView,该视图应该使用ACCESSIBILITY_LIVE_REGION_POLITE模式被标记为一个实时区域。这是无障碍服务的责任,控制TYPE_WINDOW_CONTENT_CHANGED 事件标识实时区域节点和其子元素的变化。实时区域模式,或如果视图不是个实时区域,返回ACCESSIBILITY_LIVE_REGION_NONE。
getMaxTextLength() 返回该节点的最大文本长度。
getMovementGranularities() 获取遍历该节点文本的移动粒度。
getPackageName() 获取该节点来自的包名。
getParent() 获取父级NodeInfo。
getRangeInfo() 如果节点是个范围,获取范围信息AccessibilityNodeInfo.RangeInfo
getText() 获取该节点的文本。
getTextSelectionEnd() 选择文本的末尾,如果没有选择文本,返回光标位置,或如果不存在选择文本和光标,返回-1。
getTextSelectionStart() 选择文本的起始,如果没有选择文本,返回光标位置,或如果不存在选择文本和光标,返回-1。
getViewIdResourceName() 获取源视图 id 的完全合格源名称。
getWindowId() 获取该信息来自的窗口的id。
hashCode() 返回该对象的哈希编码值。多用于判断node是否相同
isAccessibilityFocused() 获取该节点是否可被无障碍聚焦。
isCheckable() 获取该节点是否可选中。
isChecked() 获取该节点是否已选中。
isClickable() 获取该节点是否可点击。
isContentInvalid() 获取该节点的内容是否已失效。例如,一个日期数据格式不正确。
isDismissable() 获取该节点是否可被关闭。
isEditable() 获取该节点是否可编辑。
isEnabled() 获取该节点是否可用。
isFocusable() 获取该节点是否可获取焦点。
isFocused() 获取该节点是否已被聚焦。
isLongClickable() 获取该节点是否可长按点击。
isMultiLine() 获取该节点是否是个多行可编辑文本。
isPassword() 获取该节点是否是个密码。
isScrollable() 获取该节点是否可滚动。
isSelected() 获取该节点是否已被选择。
isVisibleToUser() 该节点是否对用户可见。
obtain(View root, int virtualDescendantId) 如果可获得,返回一个缓存实例,否则创建一个新的并设置源。 View:虚拟子树的根。 int:虚拟后代的id。返回一个实例化的AccessibilityNodeInfo
obtain(AccessibilityNodeInfo info) 如果可获得,返回一个缓存实例,或创建一个新的。返回的实例初始化自一个给定 root。
obtain() 如果可获得,返回一个缓存实例,否则,返回一个新的。
obtain(View source) 如果可获得,返回一个缓存实例,否则,返回一个新的并设置源。View:源视图。
performAction(int action, Bundle arguments) 在该节点上执行一个操作。int: 要执行的操作。Bundle:具有额外参数的包。返回一个布尔值,表示是否成功执行操作。
performAction(int action) 在该节点上执行一个操作。
recycle() 返回一个实例重复使用,回收掉当前的实例。
refresh() 刷新视图呈现的最新状态信息。返回一个布尔值,表示是否刷新成功。
removeAction(int action) 该方法在 API 级别 21 被弃用。
setAccessibilityFocused(boolean focused) 设置该节点可无障碍聚焦。
setBoundsInParent(Rect bounds) 在父级坐标中设置节点边界。
setBoundsInScreen(Rect bounds) 在屏幕坐标中设置节点边界。
setCanOpenPopup(boolean opensPopup) 设置该节点可打开一个弹窗或对话框。
setCheckable(boolean checkable) 设置该节点可选中。
setChecked(boolean checked) 设置该节点已选中。
setClassName(CharSequence className) 设置该节点来自的类。
setClickable(boolean clickable) 设置该节点可点击。
setCollectionInfo(AccessibilityNodeInfo.CollectionInfo collectionInfo) 如果该节点是个集合,设置集合信息。一个集合子集通常也是个集合项目。
setContentDescription(CharSequence contentDescription) 设置该节点的内容描述。
setContentInvalid(boolean contentInvalid) 设置节点内容无效。例如,一个日期数据格式不正确。
setContextClickable(boolean contextClickable) 设置该节点文本可点击。
setDismissable(boolean dismissable) 设置该节点可以被关闭。
setEditable(boolean editable) 设置该节点可编辑。
setEnabled(boolean enabled) 设置该节点可用。
setFocusable(boolean focusable) 设置该节点可聚焦。
setFocused(boolean focused) 设置该节点已聚焦。
setInputType(int inputType) 设置源中的输入类型为inputType
setLabelFor(View root, int virtualDescendantId) 为无障碍目的,设置可作为标签代表视图的信息。如果 virtualDescendantId 为NO_ID,根被设置为标签。一个虚拟后代是一个虚构视图,为无障碍目的,将自己报告为视图层次的一部分。该操作可以使绘制复杂内容的自定义视图,将自己报告为虚拟视图树,然后传递其逻辑结构。
setLabelFor(View labeled) 为无障碍目的,设置可作为标签代表视图的信息。
setLabeledBy(View label) 为无障碍目的,设置可作为标签代表视图的信息。
setLabeledBy(View root, int virtualDescendantId) 为无障碍目的,设置可作为标签代表视图的信息。如果 virtualDescendantId 为NO_ID,根被设置为标签。一个虚拟后代是一个虚构视图,为无障碍目的,将自己报告为视图层次的一部分。该操作可以使绘制复杂内容的自定义视图,将自己报告为虚拟视图树,然后传递其逻辑结构。
setLiveRegion(int mode) 设置该节点的实时区域模式。int:实时区域模式,或如果视图不是个实时区域时,为ACCESSIBILITY_LIVE_REGION_NONE。
setLongClickable(boolean longClickable) 设置该节点可长按点击。
setMaxTextLength(int max) 设置最大文本长度,或无限制时为-1。一般情况下,用来标识一个可编辑文本框有输入字符数目限制。
getMovementGranularities() 设置遍历节点文本的移动粒度。
setMultiLine(boolean multiLine) 设置该节点为一个多行可编辑文本。
setPackageName(CharSequence packageName) 设置该节点来自的包。
setParent(View root, int virtualDescendantId) 设置给定 root 虚拟后代的父元素。如果 virtualDescendantId 等于 NO_ID,该root 被设置为父级。一个虚拟后代是一个虚构视图,为无障碍目的,将自己报告为视图层次的一部分。该操作可以使绘制复杂内容的自定义视图,将自己报告为虚拟视图树,然后传递其逻辑结构。
setParent(View parent) 设置父元素。
setPassword(boolean password) 设置该节点为密码。
setRangeInfo(AccessibilityNodeInfo.RangeInfo rangeInfo) 如果该节点是个范围,设置范围信息。
setScrollable(boolean scrollable) 设置该节点可滚动。
setSelected(boolean selected) 设置该节点是否已选择。
setSource(View source) 设置信息源。
setSource(View root, int virtualDescendantId) 为给定 root 虚拟后代设置源。如果 virtualDescendantId 等于 NO_ID,该 root被设置为源。一个虚拟后代是一个虚构视图,为无障碍目的,将自己报告为视图层次的一部分。该操作可以使绘制复杂内容的自定义视图,将自己报告为虚拟视图树,然后传递其逻辑结构。
setText(CharSequence text) 设置该节点的文本。
setTextSelection(int start, int end) 设置文本选择的起始和结尾。
setViewIdResourceName(String viewIdResName) 设置源视图id的资源名称
setVisibleToUser(boolean visibleToUser) 设置该节点对用户可见。
toString() 返回一个代表对象的字符串。 getClass().getName() + ‘@’ + Integer.toHexString(hashCode())
writeToParcel(Parcel parcel, int flags) 封装该对象到一个包中。
API 21
getError() API Level 21 获取该节点的错误文本。
setError(CharSequence error) API Level 21 设置该节点的错误文本。
getWindow() API Level 21 获取该节点所属的窗口。AccessibilityWindowInfo
removeAction(AccessibilityNodeInfo.AccessibilityAction action) API Level 21 移除一个可以在该节点上执行的操作。如果该操作未被添加到该节点,调用该方法没有任何效果。返回一个布尔值表示是否成功移除操作。
removeChild(View root, int virtualDescendantId) API Level 21 移除给定根节点的一个虚拟子元素。如果子元素不是之前被添加到该节点的,调用该方法无效果。 返回一个布尔值表示是否存在子元素。
removeChild(View child) API Level 21 移除一个子元素。如果子元素先前未被添加到该节点,调用该方法无效果。
API 22
getTraversalAfter() API Level 22 当前节点被访问后,获取无障碍遍历中的下一个节点。一个屏幕阅读器必须在访问该节点内容之前,访问其他节点的内容。如果存在,返回后续节点,否则,返回 null。
getTraversalBefore() API Level 22 当前节点被访问后,获取无障碍遍历中的上一个节点。屏幕阅读器必须访问该节点的信息,在访问先前节点内容之前。
setTraversalAfter(View view) API Level 22 设置无障碍遍历中下一个被访问的视图。一个屏幕阅读器在访问该节点内容之前,必须访问另一个节点的内容。
setTraversalAfter(View root, int virtualDescendantId) API Level 22设置无障碍遍历中下一个被访问的视图。一个屏幕阅读器在访问该节点内容之前,必须访问另一个节点的内容。如果 virtualDescendantId 等于 NO_ID,root被设置为前任。一个虚拟后代是一个虚构视图,为无障碍目的,将自己报告为视图层次的一部分。该操作可以使绘制复杂内容的自定义视图,将自己报告为虚拟视图树,然后传递其逻辑结构。
setTraversalBefore(View view) API Level 22 设置无障碍遍历中当前访问节点的上一个视图。一个屏幕阅读器在访问上一个节点之前,必须访问该节点的内容。
setTraversalBefore(View root, int virtualDescendantId) API Level 22 设置无障碍遍历中当前访问节点的上一个视图。一个屏幕阅读器在访问上一个节点之前,必须访问该节点的内容。如果virtualDescendantId 等于 NO_ID,root被设置为后任。一个虚拟后代是一个虚构视图,为无障碍目的,将自己报告为视图层次的一部分。该操作可以使绘制复杂内容的自定义视图,将自己报告为虚拟视图树,然后传递其逻辑结构。
API 23
isContextClickable() API Level 23 获取该节点是否上下文可点击。
API 24
setImportantForAccessibility(boolean important) API Level 24 设置该节点对无障碍很重要。
setDrawingOrder(int drawingOrderInParent) API Level 24 设置该节点相关视图的绘制顺序。
getDrawingOrder() API Level 24。获取该节点中视图的相对绘制顺序。绘制顺序只决定于节点的父级,所以该索引只与其兄弟姐妹相关。在一些情景下,绘制顺序是基本同步的,所以两个兄弟姐妹的返回值相同是可能的。返回值会被跳过也是可能的。
isImportantForAccessibility() API Level 24 返回该节点是否来源于一个对无障碍相当重要的视图。

performGlobalAction

Action 释义
GLOBAL_ACTION_BACK 相当于点击物理按键返回
GLOBAL_ACTION_HOME 相当于点击物理按键Home键
GLOBAL_ACTION_NOTIFICATIONS 相当于下滑打开通知
GLOBAL_ACTION_RECENTS 相当于点击物理按键最近任务键
GLOBAL_ACTION_QUICK_SETTINGS 打开快速设置
GLOBAL_ACTION_POWER_DIALOG 打开长按电源键的弹框

public class MyAccessibilityService extends AccessibilityService {
 	/**
 	 该方法在初始化辅助功能服务时调用,可以在这时做相应的初始化工作。
 	*/
    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
    }
 
 	/**
 	 在获取到指定的监听事件时,通过回调这个方法来进行对应的操作
 	*/
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        // 1.AccessibilityEvent中一些常用的使用方法
        // 这里我们获取到该辅助功能的事件类型
        // 事件类型请参照 2.1.3中AccessibilityEventTypes表
        int eventType = event.getEventType();
        // 输出事件的字符串type
        String typeStr = event.eventTypeToString(eventType);
        // 根据事件类型来分发我们的需要的操作,这里以窗口变化为例
        if(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == eventType){
            // 判断我们的辅助功能是否在约定好的应用界面执行,以设置界面为例
            if("com.android.settings".equals(event.getPackageName()){
                // doSomeThing
            }
        } else if(AccessibilityEvent.TYPE_GESTURE_DETECTION_START == eventType) {
            // 在监测到手势的时候
        } else {
            // 在完成操作时,可以关闭自己的服务,下次使用再次开启。
            // API > = 24
            disableSelf();
        }
 
        // 2.通过event来遍历我们的nodeInfo
        if (VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
            // 这里使用getResource()方法其实是从AccessibilityEvent继承的
            // AccessibilityRecord中抽取AccessibilityNodeInfo
            // 实际调用的是AccessibilityRecord中的方法,返回的是AccessibilityNodeInfo mSourceNode
            AccessibilityNodeInfo info = event.getSource();
        else
            info = getRootInActiveWindow();
 
        // 3.遍历info中的子节点
        if (info.getChildCount()= 0){
            // 通过一个循环将info的子节点遍历
            for (int i = 0; i < info.getChildCount(); i++) {
                // 获取子节点中某个特定的node,这里通过以下方法通过ID查找
                List<AccessibilityNodeInfo> list = info.findAccessibilityNodeInfosByViewId("com.android" +".settings:id/xxxx");
                // 通过text查找
                List<AccessibilityNodeInfo> list = info.findAccessibilityNodeInfosByText("xxxx");
                // 打印nodeinfo的信息
                Log.e("InfoType: " + info.getClassName());
                Log.e("InfoText: " + info.getText());
                Log.e("InfoPkgName: " + info.getPackageName());
                Log.e("InfoViewId: " + info.getViewIdResourceName());
            }
        }
 
        // 4.为节点添加操作
        // 1) 首先获取到我们的节点
        AccessibilityNodeInfo info = event.getSource();
        // 2) 通过查找指定的ID、text来查找一个系列的节点,返回一个list,需要判断list.size()是否为空
        List<AccessibilityNodeInfo> list = info.findAccessibilityNodeInfosByViewId("pkgName." + "id");
        AccessibilityNodeInfo info = list.get(0);
        // 3) 为节点添加操作,点击事件(事件可参照AccessibilityNodeInfo表)
        info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        // 4) 添加node可用的action,给node添加一个可清除焦点的操作
        // 通过addAction(AccessibilityNodeInfo.AccessibilityAction action)
        info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLEAR_FOCUS);
        // 获取该node上可用的action属性list,可以用来查看该node的属性
        List<AccessibilityNodeInfo.AccessibilityAction> listAction = info.getActionList();
 
        // 5.获取该节点上子节点个数
        int childCount = info.getChildCount();
 
        // 6.操作完成后,回收实例,返回一个下次可用的实例
        info.recycle();
 
        // 需要注意的是,在node.performAction之后,调用本地广播的话,之后的globeAction不会起作用,例:
        sureStopNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        sureStopNode.recycle();
        SystemMessage.getInstance().send(SystemMessage.ACTION_POWER_BOOSTER_NEXT);
        performGlobalAction();// 这句话是不起作用的
 
        // 7.辅助功能的一些适用场景:
        // 1)部分应用中获取短信验证码(通过开启辅助功能的方式获取)
        //  - 监听通知栏的消息(typeNotificationStateChanged)
        //  - 弹出通知栏的时候获取该通知的节点信息(event.getSource())
        //  - 遍历root节点,取得显示信息的文本Node(info.findAccessibilityNodeInfosByViewId("pkgName." + "id"))
        //  - 通过NodeInfo.getText()方法获取到相应的文本信息,并取出验证码
        //  - 取消掉通知栏弹出框
        //  - 获取到要输入的EditText获取直接在本应用给需要填写验证码的区域设置文本。
 
        // 2)部分应用中恢复APP的初始设置(清除APP的数据)
        //  - 跳转到应用详情,通过findAccessibilityNodeInfosByViewId查找节点
        //  - 通过节点info.performAction(AccessibilityNodeInfo.ACTION_CLICK)点击清除
        //  - 弹出确定对话框,同上方式找到确定节点,点击后返回
 
        // 3)监测应用是否在前台,APP的启动(通过windowstatechange事件获取到当前的event的pkgName)
        //  - 通过接收typeWindowStateChanged事件,获取event的pkgName确定哪个应用启动或者在最上层显示(悬浮窗不适用)
 
        // 4)自动安装与卸载软件
        //  - 同3,寻找相应的节点,点击事件
 
        // 5)自动化UI测试
 
        // 6)最常见的抢红包
 
        // 7)通过辅助功能开启一些权限(不需要用户手动点击开启了)
        //  - 在用户确定需要开启权限时,自动跳转,寻找相应的开关按钮
        //  - 需要注意的是,部分开关(switch button, checkbox)可能没有ID,需要通过info.getClassName()来判断,属于那种类型的view。
    }
 
 	/**
 	  系统想要中断辅助功能时会调用该方法
 	*/
    @Override
    public void onInterrupt() {
    }
 
}
public class MyAccessibilityService extends AccessibilityService {
 
    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            info.flags = AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
        } else {
            info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;
        }
        info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
        info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
        info.notificationTimeout = 100;
        setServiceInfo(info);
    }
 
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            AccessibilityButtonController mAccessibilityButtonController = getAccessibilityButtonController();
            mAccessibilityButtonController.registerAccessibilityButtonCallback(new AccessibilityButtonController.AccessibilityButtonCallback() {
                @Override
                public void onClicked(AccessibilityButtonController controller) {
                    super.onClicked(controller);
                    // 底部导航栏中辅助功能按钮点击事件回调
                    Toast.makeText(MyAccessibilityService.this, "on Click", Toast.LENGTH_SHORT).show();
                }
 
                @Override
                public void onAvailabilityChanged(AccessibilityButtonController controller, boolean available) {
                    super.onAvailabilityChanged(controller, available);
                    // 辅助功能可用性改变的回调。返回了辅助功能底部按钮是否可用的布尔值,和按钮控制器
                    // available = true 表示该按钮对本服务可用
                    // available = false 是由于设备显示了按钮,或按钮被分配到另一个服务或其他原因。
                }
            });
        }
    }
 
    @Override
    public void onInterrupt() {
    }
}

FingerprintGestureController
常量

常量 描述
FINGERPRINT_GESTURE_SWIPE_DOWN 指纹手势下滑。
FINGERPRINT_GESTURE_SWIPE_LEFT 指纹手势左滑。
FINGERPRINT_GESTURE_SWIPE_RIGHT 指纹手势右滑。
FINGERPRINT_GESTURE_SWIPE_DOWN 指纹手势上滑。

方法

方法 描述
isGestureDetectionAvailable() 判断手势监测是否可用。
registerFingerprintGestureCallback(FingerprintGestureController.FingerprintGestureCallback callback, Handler handler) 通过该方法注册一个指纹手势的回调。
unregisterFingerprintGestureCallback(FingerprintGestureController.FingerprintGestureCallback callback) 取消注册。
registerFingerprintGestureCallback(FingerprintGestureController.FingerprintGestureCallback, Handler) 取消注册。
onGestureDetected(int gesture) 这里获取到相应的手势。
onGestureDetectionAvailabilityChanged(boolean available) 这里返回了手势监测是否可用。

需要注意的是:
addAction(AccessibilityNodeInfo.AccessibilityAction action)setDrawingOrder(int drawingOrderInParent)不能在辅助服务中调用,否则会抛出异常java.lang.IllegalStateException: Cannot perform this action on a sealed instance.


本文参考Android辅助功能


致敬前辈,砥砺前行!

发布了68 篇原创文章 · 获赞 108 · 访问量 19万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览