-
什么是无障碍服务
无障碍服务应该只用于帮助有残疾的用户使用Android设备和应用程序。它们在后台运行,并在AccessibilityEvents被触发时接收系统的回调。这样的事件表示用户界面中的一些状态转换,例如,焦点发生了变化,按钮被点击,等等。这样的服务可以选择性地请求查询活动窗口内容的功能。可访问性服务的开发需要扩展该类并实现其抽象方法。 -
无障碍服务有什么作用
无障碍服务的好处很多,可以实现一键操作,帮助残障人士使用手机。当然坏处也有,开启无障碍服务以后,因为服务对手机的实时监控,会引起手机的卡顿。当用户同意我们的应用获取无障碍服务的权限之后就可以模拟操作,来控制用户的手机。无障碍被广泛用于抢红包、自动回复、一键获取权限、一键自动分享等应用中。 -
如何去使用无障碍服务.
步骤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包名,这里使用微信测试