初探无障碍服务

无障碍服务官网文档AccessibilityService

  1. 什么是无障碍服务
    无障碍服务应该只用于帮助有残疾的用户使用Android设备和应用程序。它们在后台运行,并在AccessibilityEvents被触发时接收系统的回调。这样的事件表示用户界面中的一些状态转换,例如,焦点发生了变化,按钮被点击,等等。这样的服务可以选择性地请求查询活动窗口内容的功能。可访问性服务的开发需要扩展该类并实现其抽象方法。

  2. 无障碍服务有什么作用
    无障碍服务的好处很多,可以实现一键操作,帮助残障人士使用手机。当然坏处也有,开启无障碍服务以后,因为服务对手机的实时监控,会引起手机的卡顿。当用户同意我们的应用获取无障碍服务的权限之后就可以模拟操作,来控制用户的手机。无障碍被广泛用于抢红包、自动回复、一键获取权限、一键自动分享等应用中。

  3. 如何去使用无障碍服务.

步骤1:首先需要创建一个服务类AccessibilityServiceName

import android.accessibilityservice.AccessibilityService
import android.content.Intent
import android.util.Log
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityEvent.
const val Tag = "[Accessibility]->"
class AccessibilityServiceName : AccessibilityService() {


    /**
     * 服务开启时,调用setServiceInfo();这个方法同样可以实现xml中的配置信息
     * 可以做一些开启后的操作比如点两下返回
     */
    override fun onServiceConnected() {
        super.onServiceConnected()
        Log.v(Tag, "onServiceConnected")
    }

    /**
     * 关闭服务时,调用
     * 如果有资源记得释放
     */
    override fun onUnbind(intent: Intent?): Boolean {
        Log.v(Tag, "onUnbind")
        return super.onUnbind(intent)
    }


    /**
     * 这个方法是我们用的最多的方法,我们会在这个方法里写大量的逻辑操作。
     * 通过对event的判断执行不同的操作
     * 当窗口发生的事件是我们配置监听的事件时,会回调此方法.会被调用多次
     */
    override fun onAccessibilityEvent(event: AccessibilityEvent?) {
        Log.v(Tag, "onAccessibilityEvent() = ${event.toString()}")
        event?.let {
            when (it.action) {
                TYPE_VIEW_CLICKED -> {

                }
            }
        }
    }


    /**
     * 当服务要被中断时调用.会被调用多次
     */
    override fun onInterrupt() {
        Log.v(Tag, "onInterrupt")
    }
}

步骤2:在AndroidManifest.xml清单文件配置相应的权限是注册服务

 <uses-permission
        android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
        tools:ignore="ProtectedPermissions" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

     
        <service
            android:name=".AccessibilityServiceName"
             //无障碍服务名字
            android:label="@string/accessibility_service_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>
    </application>

配置所需权限

    <uses-permission
        android:name="android.permission.BIND_ACCESSIBILITY_SERVICE"
        tools:ignore="ProtectedPermissions" />

步骤3:在res资源文件下床架xml文件夹,然后再xml文件夹创建accessibility_service_config无障碍服务配置


<!-- <accessibility-service
<!--    //用于描述此服务的信息,会显示在系统开启服务的设置界面-->
<!--    android:description="@string/app_accessibility_description"-->
<!--    //接收EventTypes 需要辅助的app包名,不写表示所有app。-->
<!--    android:packageNames="com.tencent.mm,com.tencent.mobileqq"-->
<!--    //可以接收的事件,这里这是typeAllMask就是接收所有的,注意这里接受的方法多了也会卡。-->
<!--    android:accessibilityEventTypes="typeAllMask"-->
<!--    //字面意思:反馈类型.官方解释真的"很详细".-->
<!--    android:accessibilityFeedbackType="feedbackAllMask"-->
<!--    //发送2次事件的时间间隔,超过后事件作废-->
<!--    android:notificationTimeout="100"-->
<!--    //设置界面,在系统的启动服务界面会出现一个设置按钮,用来打开这个Activity的;-->
<!--    android:settingsActivity="com.angcyo.SettingsActivity"-->
<!--    //官方解释很模糊,暂且就使用缺省值吧-->
<!--    android:accessibilityFlags="flagDefault"-->
<!--    //表明此服务是否可以读取窗口中的内容,应该是最重要的属性了.在运行时不可修改;-->
<!--    android:canRetrieveWindowContent="true"/>-->

其中accessibilityEventTypes的属性值表

 <attr name="accessibilityEventTypes">
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} events.-->
            <flag name="typeViewClicked" value="0x00000001" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED} events. -->
            <flag name="typeViewLongClicked" value="0x00000002" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED} events. -->
            <flag name="typeViewSelected" value="0x00000004" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED} events. -->
            <flag name="typeViewFocused" value="0x00000008" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED} events. -->
            <flag name="typeViewTextChanged" value="0x00000010" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED} events. -->
            <flag name="typeWindowStateChanged" value="0x00000020" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED} events. -->
            <flag name="typeNotificationStateChanged" value="0x00000040" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER} events. -->
            <flag name="typeViewHoverEnter" value="0x00000080" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT} events. -->
            <flag name="typeViewHoverExit" value="0x00000100" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START} events. -->
            <flag name="typeTouchExplorationGestureStart" value="0x00000200" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END} events. -->
            <flag name="typeTouchExplorationGestureEnd" value="0x00000400" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} events. -->
            <flag name="typeWindowContentChanged" value="0x00000800" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED} events. -->
            <flag name="typeViewScrolled" value="0x000001000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED} events. -->
            <flag name="typeViewTextSelectionChanged" value="0x000002000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_ANNOUNCEMENT} events. -->
            <flag name="typeAnnouncement" value="0x00004000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUSED} events. -->
            <flag name="typeViewAccessibilityFocused" value="0x00008000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED} events. -->
            <flag name="typeViewAccessibilityFocusCleared" value="0x00010000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY} events. -->
            <flag name="typeViewTextTraversedAtMovementGranularity" value="0x00020000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_START} events. -->
            <flag name="typeGestureDetectionStart" value="0x00040000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_GESTURE_DETECTION_END} events. -->
            <flag name="typeGestureDetectionEnd" value="0x00080000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_START} events. -->
            <flag name="typeTouchInteractionStart" value="0x00100000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_INTERACTION_END} events. -->
            <flag name="typeTouchInteractionEnd" value="0x00200000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_WINDOWS_CHANGED} events. -->
            <flag name="typeWindowsChanged" value="0x00400000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CONTEXT_CLICKED} events. -->
            <flag name="typeContextClicked" value="0x00800000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPE_ASSIST_READING_CONTEXT} events. -->
            <flag name="typeAssistReadingContext" value="0x01000000" />
            <!-- Receives {@link android.view.accessibility.AccessibilityEvent#TYPES_ALL_MASK} i.e. all events. -->
            <flag name="typeAllMask" value="0xffffffff" />
        </attr>

步骤4:在activity中测试列子


import android.accessibilityservice.AccessibilityServiceInfo
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.View
import android.view.accessibility.AccessibilityManager
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {



    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<View>(R.id.btnClick).setOnClickListener {
            if (!isOpenAccessibilityServiced(this@MainActivity)) {
                val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                startActivity(intent)
            } else {
                Log.i(Tag, "已开启无障碍服务.");
            }
        }
    }


    /**
     * 是否开启无障碍服务
     */
    private fun isOpenAccessibilityServiced(context: Context): Boolean {
        var isStartAccessibilityServiceEnable = false
        val accessibilityManager =
            context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
        if (accessibilityManager != null) {
            val accessibilityServices =
                accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK) as List<AccessibilityServiceInfo>
            for (info in accessibilityServices) {
                if (info.id.contains(context.packageName)) {
                    isStartAccessibilityServiceEnable = true;
                    Log.i(Tag, "已开启无障碍服务.");
                    break
                }
            }
        }
        return isStartAccessibilityServiceEnable
    }

}

步骤5:测试结果截图
1、打开和关闭无障碍服务

在这里插入图片描述

2、需要辅助app包名,这里使用微信测试

在这里插入图片描述

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

将哥哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值