龙兴居士 發表於 2023-1-6 18:50:00

Android开发 AccessibilityService无障碍服务

<h1><span style="color: rgba(0, 128, 128, 1)">前言</span></h1>
<p>  此篇博客主要记录如何开启无障碍服务与功能使用。google的设计这个功能是用来帮助残障人士使用设备。 也能帮助我们开发者进行各种各样的全局事件监听(按键、触控手势、UI变化)这样可以免于修改framework插入事件监听。当然启动条件比较苛刻,需要用户手动打开,所以在正常的应用上应该用不上此功能。但是系统级别的应用上我们可以通过反射直接开启。 还有一些人还会使用此服务进行自动抢微信红包的无语行为。个人是测试转开发,我体验后无障碍服务更像是自动化uiautomator2测试的里的翻版。</p>
<h1><span style="color: rgba(0, 128, 128, 1)">添加无障碍服务</span></h1>
<h2><span style="color: rgba(0, 51, 102, 1)">第一步 创建AccessibilityService服务类</span></h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.accessibilityservice.AccessibilityService
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.content.Intent
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.content.ServiceConnection
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.util.Log
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.view.KeyEvent
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.view.accessibility.AccessibilityEvent

</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> AccessibilityService : AccessibilityService() {

    override fun bindService(service: Intent</span>?<span style="color: rgba(0, 0, 0, 1)">, conn: ServiceConnection, flags: Int): Boolean {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.bindService(service, conn, flags)
    }

    override fun onCreate() {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onCreate()
    }

    override fun onDestroy() {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onDestroy()
    }

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 无障碍服务的生命周期,表明服务已经连接成功
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    override fun onServiceConnected() {
      </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onServiceConnected()
    }

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   *当系统想要中断您的服务正在提供的反馈(通常是为了响应将焦点移到其他
   *控件等用户操作)时,就会调用此方法。此方法可能会在您的服务的整个生命
   *周期内被调用多次。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    override fun onInterrupt() {
    }

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 当用户在触摸屏上执行特定手势时由系统调用。注意:为了接收手势,
   * 辅助服务必须通过设置AccessibilityServiceInfo请求设备处于触摸探索模式FLAG_REQUEST_TOUCH_EXPLORATION_MOD
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    override fun onGesture(gestureId: Int): Boolean {
      Log.e(</span>"zh", "onGesture: ${gestureId}"<span style="color: rgba(0, 0, 0, 1)">)
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onGesture(gestureId)
    }

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   *当系统检测到与无障碍服务指定的事件过滤参数匹配的 AccessibilityEvent
   *时,就会回调此方法。例如,当用户点击按钮,或者聚焦于某个应用(无障碍
   *服务正在为该应用提供反馈)中的界面控件时。出现这种情况时,系统会调用
   *此方法,并传递关联的 AccessibilityEvent,然后服务会对该类进行解释并
   *使用它来向用户提供反馈。此方法可能会在您的服务的整个生命周期内被调用多次。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    override fun onAccessibilityEvent(event: AccessibilityEvent) {
      Log.e(</span>"zh", "无障碍服务 onAccessibilityEvent:${event}"<span style="color: rgba(0, 0, 0, 1)">)
      when(event.eventType){
            AccessibilityEvent.TYPE_ANNOUNCEMENT</span>-&gt; Log.e("zh", "应用程序发布公告的事件"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED </span>-&gt; Log.e("zh", "View的焦点"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED </span>-&gt; Log.e("zh", "View的焦点清除"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED </span>-&gt; Log.e("zh", "通知栏状态更新"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_HOVER_ENTER </span>-&gt; Log.e("zh", "View的鼠标悬停选中"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_HOVER_EXIT </span>-&gt; Log.e("zh", "View的鼠标悬停离开"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START </span>-&gt; Log.e("zh", "开始触摸探索手势的事件"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END </span>-&gt; Log.e("zh", "结束触摸探索手势的事件"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED </span>-&gt; Log.e("zh", "窗口内容更新"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_SCROLLED </span>-&gt; Log.e("zh", "滚动类View"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_SELECTED </span>-&gt; Log.e("zh", "表示通常在android.widget.AdapterView的上下文中选择项的事件"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED </span>-&gt; Log.e("zh", "EditText视图选中内容改变"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED </span>-&gt; Log.e("zh", "EditText视图内容改变"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY </span>-&gt; Log.e("zh", "表示以给定的移动粒度遍历视图文本的事件"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_CLICKED </span>-&gt; Log.e("zh", "点击事件"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_LONG_CLICKED </span>-&gt; Log.e("zh", "长按点击事件"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED </span>-&gt; Log.e("zh", "表示在android.view.View上的上下文单击事件"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_GESTURE_DETECTION_START </span>-&gt; Log.e("zh", "开始手势检测"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_GESTURE_DETECTION_END </span>-&gt; Log.e("zh", "结束手势检测"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_TOUCH_INTERACTION_START </span>-&gt; Log.e("zh", "表示用户开始触摸屏幕的事件"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_TOUCH_INTERACTION_END </span>-&gt; Log.e("zh", "表示用户结束触摸屏幕的事件"<span style="color: rgba(0, 0, 0, 1)">)
            AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT </span>-&gt; Log.e("zh", "表示助手当前正在读取用户屏幕上下文的事件。"<span style="color: rgba(0, 0, 0, 1)">)
      }
    }

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 按键事件
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    override fun onKeyEvent(event: KeyEvent): Boolean {
      Log.e(</span>"zh", "onKeyEvent: ${event}"<span style="color: rgba(0, 0, 0, 1)">)
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.onKeyEvent(event)
    }
}</span></pre>
</div>
<p>&nbsp;</p>
<h2><span style="color: rgba(0, 51, 102, 1)">第二步 在xml资源目录下添加配置xml</span></h2>
<p><img src="https://img2023.cnblogs.com/blog/1497956/202301/1497956-20230106182206724-1804606511.png" alt="" loading="lazy"></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">accessibility-service </span><span style="color: rgba(255, 0, 0, 1)">xmlns:android</span><span style="color: rgba(0, 0, 255, 1)">="http://schemas.android.com/apk/res/android"</span><span style="color: rgba(255, 0, 0, 1)">
    android:description</span><span style="color: rgba(0, 0, 255, 1)">="@string/accessibility_service_name"</span><span style="color: rgba(255, 0, 0, 1)">
    android:packageNames</span><span style="color: rgba(0, 0, 255, 1)">="com.zh.XXX,com.android.systemui"</span><span style="color: rgba(255, 0, 0, 1)">
    android:accessibilityEventTypes</span><span style="color: rgba(0, 0, 255, 1)">="typeAllMask"</span><span style="color: rgba(255, 0, 0, 1)">
    android:accessibilityFeedbackType</span><span style="color: rgba(0, 0, 255, 1)">="feedbackGeneric"</span><span style="color: rgba(255, 0, 0, 1)">
    android:accessibilityFlags</span><span style="color: rgba(0, 0, 255, 1)">="flagDefault|flagRetrieveInteractiveWindows|flagIncludeNotImportantViews"</span><span style="color: rgba(255, 0, 0, 1)">
    android:notificationTimeout</span><span style="color: rgba(0, 0, 255, 1)">="100"</span><span style="color: rgba(255, 0, 0, 1)">
    android:canPerformGestures</span><span style="color: rgba(0, 0, 255, 1)">="true"</span><span style="color: rgba(255, 0, 0, 1)">
    android:canRetrieveWindowContent</span><span style="color: rgba(0, 0, 255, 1)">="true"</span> <span style="color: rgba(0, 0, 255, 1)">/&gt;</span></pre>
</div>
<p><strong>android:description</strong> 此属性是在无障碍服务启用页面的描述</p>
<p><strong> android:packageNames</strong>&nbsp; 此属性代表你需要那些应用支持无障碍服务,如果什么都不填删除此属性则代表你想监听设备的全部应用</p>
<p><span id="androidaccessibilityeventtypes-事件类型"><strong>android:accessibilityEventTypes</strong> 事件类型AccessibilityService服务响应的事件类型,只有声明了的类型,系统才会调用该服务的onAccessibilityEvent,有以下几个事件类型提供选择:</span></p>
<p><span>  </span>typeViewClicked&nbsp; 点击事件 | typeViewSelected&nbsp; View被选择 | typeViewScrolled&nbsp; &nbsp;滑动事件 | typeWindowContentChanged&nbsp; &nbsp;窗口内容该表 |&nbsp;typeAllMask&nbsp; &nbsp;所有事件</p>
<p><span><span id="androidaccessibilityfeedbacktype-反馈类型"><strong>android:accessibilityFeedbackType</strong> 反馈类型</span></span></p>
<p><span><span>  </span></span>feedbackSpoken 语音反馈 | feedbackHaptic 触觉(震动)反馈 | feedbackAudible 音频反馈 | feedbackVisual 视频反馈 | feedbackGeneric 通用反馈&nbsp; | feedbackAllMask 以上都具有</p>
<span id="androidaccessibilityflags-额外声明"><strong>android:accessibilityFlags</strong> 额外声明</span>
<p>  flagDefault 默认</p>
<p>  flagIncludeNotImportantViews&nbsp;</p>
<p>  flagRequestTouchExplorationMode&nbsp; 允许获得触控信息,另外你还需要将android:canRequestTouchExplorationMode&nbsp;&nbsp;属性设置为true。 <span style="color: rgba(255, 0, 0, 1)"><strong>请注意!此属性有一定的危险,添加此属性后有可能导致触控失效(触发条件可能是需要插入鼠标或者其他外置设备)</strong></span></p>
<p>  flagRequestEnhancedWebAccessibility&nbsp; 允许获取Web地址信息,另外你还需要将&nbsp;android:canRequestEnhancedWebAccessibility&nbsp;<strong>&nbsp;</strong> 属性设置为true</p>
<p>  flagReportViewIds 允许获得view id,需要获取viewid的时候需要该参数,开始没声明导致nodeInfo. getViewIdResourceName()返回的为null</p>
<p>  flagRequestFilterKeyEvents&nbsp; 此事件添加后才能在服务的onKeyEvent方法里输出当前按键键值,另外你还需要将&nbsp;android:canRequestFilterKeyEvents 属性设置为true</p>
<p>  flagRetrieveInteractiveWindows 允许获得windows,使用getWindows时需要该参数,否则会返回空列表</p>
<p><strong>android:canRetrieveWindowContent</strong>&nbsp;设置为“true”表示允许获取屏幕信息,使用getWindows、getRootInActiveWindow等函数时需要为“true”</p>
<p><strong>android:canRequestTouchExplorationMode&nbsp;&nbsp;</strong>设置为“true”表示允许获取触摸信息</p>
<p><strong>android:canRequestEnhancedWebAccessibility&nbsp;&nbsp;</strong>设置为“true”表示允许获取Web地址访问信息</p>
<p><strong>android:canRequestFilterKeyEvents&nbsp;&nbsp;</strong>设置为“true”表示允许获取按键信息</p>
<p><strong>android:canRequestFingerprintGestures&nbsp;&nbsp;</strong>设置为“true”表示允许获取手势信息</p>
<strong>android:canControlMagnification&nbsp;</strong>设置为“true”表示允许获取缩放信息
<p><strong>android:notificationTimeout</strong>&nbsp;&nbsp;同一种事件类型触发的最短时间间隔(毫秒)</p>
<h2><span style="color: rgba(0, 51, 102, 1)">第三步&nbsp; 在AndroidManifest.xml里注册服务</span></h2>
<p><span style="color: rgba(0, 0, 0, 1)">注意在android:resource 属性里添加了上面的配置xml</span></p>
<div class="cnblogs_code">
<pre>    &lt;application&gt;

      &lt;<span style="color: rgba(0, 0, 0, 1)">service
            android:name</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">.ScreenSaverAccessibilityService</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
            android:enabled</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
            android:exported</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">true</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
            android:permission</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">android.permission.BIND_ACCESSIBILITY_SERVICE</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
            &lt;intent-filter&gt;
                &lt;action android:name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">android.accessibilityservice.AccessibilityService</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
            &lt;/intent-filter&gt;
            &lt;meta-data android:name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">android.accessibilityservice</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
                android:resource</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">@xml/accessibility</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
      &lt;/service&gt;
    &lt;/application&gt;</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">第四步 启动服务</span></h2>
<p><span style="color: rgba(0, 0, 0, 1)">如果你<span style="color: rgba(255, 0, 0, 1)"><strong>不是系统级别应用</strong></span>,你需要手动去设置-无障碍中启动服务,如下图</span></p>
<p><img src="https://img2023.cnblogs.com/blog/1497956/202301/1497956-20230107104658858-651424270.png" alt="" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;如果你是系统级别应用,这可以使用下面的工具类,实现自动开启无障碍服务:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.accessibilityservice.AccessibilityServiceInfo;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.content.ComponentName;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.content.Context;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.provider.Settings;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.util.Log;
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> android.view.accessibility.AccessibilityManager;

</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> java.util.List;

</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> AccessibilityUtil {

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 关闭无障碍服务
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> context
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> autoCloseAccessibilityService(Context context){
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (isStartAccessibilityServiceEnable(context)) {
            String enabledServicesSetting </span>=<span style="color: rgba(0, 0, 0, 1)"> Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
            ComponentName selfComponentName </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> ComponentName(context.getPackageName(), ScreenSaverAccessibilityService.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.getCanonicalName());
            String flattenToString </span>=<span style="color: rgba(0, 0, 0, 1)"> selfComponentName.flattenToString();
            enabledServicesSetting</span>=enabledServicesSetting.replace(":"+flattenToString , ""<span style="color: rgba(0, 0, 0, 1)">);

            Settings.Secure.putString(context.getContentResolver(),Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,enabledServicesSetting);
            </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Settings.Secure.putInt(context.getContentResolver(),Settings.Secure.ACCESSIBILITY_ENABLED, 0);</span>
            Log.d("zh", "autoCloseAccessibilityService: SETTING ACCESSIBILITY SUCCESS!"<span style="color: rgba(0, 0, 0, 1)">);
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 开启无障碍服务
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> context
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> autoOpenAccessibilityService(Context context){
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">isStartAccessibilityServiceEnable(context)) {
            String enabledServicesSetting </span>=<span style="color: rgba(0, 0, 0, 1)"> Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
            ComponentName selfComponentName </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> ComponentName(context.getPackageName(), ScreenSaverAccessibilityService.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.getCanonicalName());
            String flattenToString </span>=<span style="color: rgba(0, 0, 0, 1)"> selfComponentName.flattenToString();
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (enabledServicesSetting==<span style="color: rgba(0, 0, 255, 1)">null</span>||
                  !<span style="color: rgba(0, 0, 0, 1)">enabledServicesSetting.contains(flattenToString)) {
                enabledServicesSetting </span>+= ":"+<span style="color: rgba(0, 0, 0, 1)">flattenToString;
            }
            Settings.Secure.putString(context.getContentResolver(),Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,enabledServicesSetting);
            Settings.Secure.putInt(context.getContentResolver(),Settings.Secure.ACCESSIBILITY_ENABLED, </span>1<span style="color: rgba(0, 0, 0, 1)">);
            Log.d(</span>"zh", "autoOpenAccessibilityService: SETTING ACCESSIBILITY SUCCESS!"<span style="color: rgba(0, 0, 0, 1)">);
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
    }

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 判断无障碍服务是否开启
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> context
   * </span><span style="color: rgba(128, 128, 128, 1)">@return</span>
   <span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">boolean</span><span style="color: rgba(0, 0, 0, 1)"> isStartAccessibilityServiceEnable(Context context) {
      AccessibilityManager accessibilityManager </span>=<span style="color: rgba(0, 0, 0, 1)"> (AccessibilityManager)context.getSystemService(Context.ACCESSIBILITY_SERVICE);
      </span><span style="color: rgba(0, 0, 255, 1)">assert</span> accessibilityManager != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
      List</span>&lt;AccessibilityServiceInfo&gt; accessibilityServices =<span style="color: rgba(0, 0, 0, 1)"> accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
      </span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (AccessibilityServiceInfo info : accessibilityServices) {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (info.getId().contains(context.getPackageName())) {
                </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
            }
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
    }
}</span></pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">第五步&nbsp; 如果无障碍服务无法连接或者创建</span></h2>
<p><span style="color: rgba(0, 0, 0, 1)">这可能是google的一些设计,可能是不允许debug安装或者内置系统应用,直接开启无障碍。 <strong>你需要重启一下设备就能恢复正常</strong>。</span></p>
<p>&nbsp;</p>
<h1><span style="color: rgba(0, 128, 128, 1)">模拟操作</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">首先在配置xml里一定要添加,否则会出现调用</span>getRootInActiveWindow()始终返回为null的问题</p>
<div class="cnblogs_code">
<pre>android:canRetrieveWindowContent="true"</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">单击操作</span></h2>
<p>&nbsp;这里举例一个单击功能,其他操作其实都是一样可以举一反三的。如果你写过uiautomator2自动化简直是信手拈来。</p>
<h3>以文本内容查找View</h3>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 根据文本查找点击设置
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    fun byTextClickSettings(){
      val nodeInfoList </span>= rootInActiveWindow.findAccessibilityNodeInfosByText("设置"<span style="color: rgba(0, 0, 0, 1)">)
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">点击</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (nodeInfoList.isNotEmpty()){
            nodeInfoList[</span>0<span style="color: rgba(0, 0, 0, 1)">].performAction(AccessibilityNodeInfo.ACTION_CLICK)
      }
    }</span></pre>
</div>
<h3>以Id查询View</h3>
<p>首先需要知道View的id,路径如下,点击monitor.bat:</p>
<p><img src="https://img2023.cnblogs.com/blog/1497956/202303/1497956-20230323105819053-1596054107.png" alt="" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;<img src="https://img2023.cnblogs.com/blog/1497956/202303/1497956-20230323110040797-1222562910.png" alt="" loading="lazy"></p>
<p>&nbsp;</p>
<p>代码:</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 根据id查找点击设置
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
    fun byIdClickSettings(){
      val nodeInfoList </span>= rootInActiveWindow.findAccessibilityNodeInfosByViewId("com.xxx.xxx:id/settings"<span style="color: rgba(0, 0, 0, 1)">)
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">点击</span>
      <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (nodeInfoList.isNotEmpty()){
            nodeInfoList[</span>0<span style="color: rgba(0, 0, 0, 1)">].performAction(AccessibilityNodeInfo.ACTION_CLICK)
      }
    }</span></pre>
</div>
<h2><span style="background-color: rgba(255, 255, 255, 1); color: rgba(0, 51, 102, 1)">焦点操作</span></h2>
<p>选中焦点</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_FOCUS =0x00000001;</pre>
</div>
<p>清除焦点</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_CLEAR_FOCUS = 0x00000002;</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">选中操作</span></h2>
<p>&nbsp;选中</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_SELECT = 0x00000004;</pre>
</div>
<p>清除选中</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_CLEAR_SELECTION = 0x00000008;</pre>
</div>
<p>多选</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_SET_SELECTION = 0x00020000;</pre>
</div>
<div class="cnblogs_code">
<pre>      Bundle arguments = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Bundle();
      arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, </span>1<span style="color: rgba(0, 0, 0, 1)">);
      arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, </span>2<span style="color: rgba(0, 0, 0, 1)">);
      info.performAction(AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments);</span></pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">滚动操作</span></h2>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 操作向前滚动节点内容。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_SCROLL_FORWARD = 0x00001000<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 操作向后滚动节点内容。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_SCROLL_BACKWARD = 0x00002000;</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">展开/收起操作</span></h2>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 展开可展开节点的操作。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_EXPAND = 0x00040000<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 折叠可展开节点的操作。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_COLLAPSE = 0x00080000;</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">撤销操作</span></h2>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 撤销可撤销节点的操作。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_DISMISS = 0x00100000;</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">进度条操作</span></h2>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * Argument for specifying the progress value to set.
   * &lt;p&gt;
   * &lt;strong&gt;Type:&lt;/strong&gt; float&lt;br&gt;
   * &lt;strong&gt;Actions:&lt;/strong&gt;
   * &lt;ul&gt;
   *   &lt;li&gt;{</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> AccessibilityNodeInfo.AccessibilityAction#ACTION_SET_PROGRESS}&lt;/li&gt;
   * &lt;/ul&gt;
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> AccessibilityNodeInfo.AccessibilityAction#ACTION_SET_PROGRESS
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String ACTION_ARGUMENT_PROGRESS_VALUE =
            "android.view.accessibility.action.ARGUMENT_PROGRESS_VALUE";</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">移动View操作</span></h2>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * Argument for specifying the x coordinate to which to move a window.
   * &lt;p&gt;
   * &lt;strong&gt;Type:&lt;/strong&gt; int&lt;br&gt;
   * &lt;strong&gt;Actions:&lt;/strong&gt;
   * &lt;ul&gt;
   *   &lt;li&gt;{</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> AccessibilityNodeInfo.AccessibilityAction#ACTION_MOVE_WINDOW}&lt;/li&gt;
   * &lt;/ul&gt;
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> AccessibilityNodeInfo.AccessibilityAction#ACTION_MOVE_WINDOW
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String ACTION_ARGUMENT_MOVE_WINDOW_X =
            "ACTION_ARGUMENT_MOVE_WINDOW_X"<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * Argument for specifying the y coordinate to which to move a window.
   * &lt;p&gt;
   * &lt;strong&gt;Type:&lt;/strong&gt; int&lt;br&gt;
   * &lt;strong&gt;Actions:&lt;/strong&gt;
   * &lt;ul&gt;
   *   &lt;li&gt;{</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> AccessibilityNodeInfo.AccessibilityAction#ACTION_MOVE_WINDOW}&lt;/li&gt;
   * &lt;/ul&gt;
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> AccessibilityNodeInfo.AccessibilityAction#ACTION_MOVE_WINDOW
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> String ACTION_ARGUMENT_MOVE_WINDOW_Y =
            "ACTION_ARGUMENT_MOVE_WINDOW_Y";</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">复制黏贴操作</span></h2>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 操作将当前选定内容复制到剪贴板。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_COPY = 0x00004000<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 操作粘贴当前剪贴板内容。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_PASTE = 0x00008000<span style="color: rgba(0, 0, 0, 1)">;

    </span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 操作以剪切当前选定内容并将其放置到剪贴板。
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_CUT = 0x00010000;</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">文本操作</span></h2>
<p>&nbsp;添加文本</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 添加文本内容,如果传入是是null这可以视为清空文本。并且光标会跳转到末尾
   * &lt;p&gt;
   * &lt;strong&gt;Arguments:&lt;/strong&gt;
   * {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> #ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE}&lt;br&gt;
   * &lt;strong&gt;Example:&lt;/strong&gt;
   * &lt;code&gt;&lt;pre&gt;&lt;p&gt;
   *   Bundle arguments = new Bundle();
   *   arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
   *       "android");
   *   info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
   * &lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_SET_TEXT = 0x00200000;</pre>
</div>
<p>向前选中文本位置</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
      请求以给定的移动粒度转到此节点文本中的前一个实体的操作。例如,移动到下一个字符、单词等。
   * &lt;p&gt;
   * &lt;strong&gt;Arguments:&lt;/strong&gt; {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}&lt;,
   * {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}&lt;br&gt;
   * &lt;strong&gt;Example:&lt;/strong&gt; Move to the next character and do not extend selection.
   * &lt;code&gt;&lt;pre&gt;&lt;p&gt;
   *   Bundle arguments = new Bundle();
   *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
   *         AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
   *   arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
   *         false);
   *   info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
   *         arguments);
   * &lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
   * &lt;/p&gt;
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #setMovementGranularities(int)
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #getMovementGranularities()
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #MOVEMENT_GRANULARITY_CHARACTER
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #MOVEMENT_GRANULARITY_WORD
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #MOVEMENT_GRANULARITY_LINE
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #MOVEMENT_GRANULARITY_PARAGRAPH
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #MOVEMENT_GRANULARITY_PAGE
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;</pre>
</div>
<p>向后选中文本位置</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 请求以给定的移动粒度转到此节点文本中的下一个实体的操作。例如,移动到下一个字符、单词等。
   * &lt;p&gt;
   * &lt;strong&gt;Arguments:&lt;/strong&gt; {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}&lt;,
   * {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN}&lt;br&gt;
   * &lt;strong&gt;Example:&lt;/strong&gt; Move to the previous character and do not extend selection.
   * &lt;code&gt;&lt;pre&gt;&lt;p&gt;
   *   Bundle arguments = new Bundle();
   *   arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
   *         AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
   *   arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN,
   *         false);
   *   info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
   * &lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
   * &lt;/p&gt;
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #setMovementGranularities(int)
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #getMovementGranularities()
   *
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #MOVEMENT_GRANULARITY_CHARACTER
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #MOVEMENT_GRANULARITY_WORD
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #MOVEMENT_GRANULARITY_LINE
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #MOVEMENT_GRANULARITY_PARAGRAPH
   * </span><span style="color: rgba(128, 128, 128, 1)">@see</span><span style="color: rgba(0, 128, 0, 1)"> #MOVEMENT_GRANULARITY_PAGE
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;</pre>
</div>
<h2><span style="color: rgba(0, 51, 102, 1)">HTML操作</span></h2>
<p><span style="color: rgba(0, 51, 102, 1)">移动HTML元素</span></p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
   * 动作移动到给定类型的下一个HTML元素。例如,移动到按钮,输入,表等。
   * &lt;p&gt;
   * &lt;strong&gt;Arguments:&lt;/strong&gt; {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> #ACTION_ARGUMENT_HTML_ELEMENT_STRING}&lt;br&gt;
   * &lt;strong&gt;Example:&lt;/strong&gt;
   * &lt;code&gt;&lt;pre&gt;&lt;p&gt;
   *   Bundle arguments = new Bundle();
   *   arguments.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_HTML_ELEMENT_STRING, "BUTTON");
   *   info.performAction(AccessibilityNodeInfo.ACTION_NEXT_HTML_ELEMENT, arguments);
   * &lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
   * &lt;/p&gt;
   </span><span style="color: rgba(0, 128, 0, 1)">*/</span>
    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">int</span> ACTION_NEXT_HTML_ELEMENT = 0x00000400;</pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>End</p>

</div>
<div id="MySignature" role="contentinfo">
    <div style="text-align: center">
    <p style="color:orange;font-size:16px;" >本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/17031369.html </p>
    <div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/17031369.html
頁: [1]
查看完整版本: Android开发 AccessibilityService无障碍服务