Android实现⾃动点击⽆障碍服务功能的实例代码ps: 不想看代码的滑到最下⾯有apk包百度⽹盘下载地址
1. 先看效果图不然都是耍流氓
2.项⽬⽬录
3.⼀些配置
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "an.autoclick"
minSdkVersion 24
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "st.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile(''), 'proguard-rules.pro'        }
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation ':core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'le.android.material:material:1.3.0'
implementation 'straintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation ':junit:1.1.2'
androidTestImplementation 'st.espresso:espresso-core:3.3.0'
//协程
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3"
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="schemas.android/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_desc" />
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="schemas.android/apk/res/android"
package="an.autoclick">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>    <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/Theme.AutoClick">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".AutoClickService"
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>
</application>
</manifest>
4.代码
AutoClickService.kt ⽆障碍服务
import android.accessibilityservice.AccessibilityService
import android.accessibilityservice.GestureDescription
import android.app.Notification
t.Intent
aphics.Path
import android.os.Build
import android.util.Log
import android.view.accessibility.AccessibilityEvent
import androidx.annotation.RequiresApi
app.NotificationCompat
utines.*
class AutoClickService : AccessibilityService() {
private val TAG = javaClass.canonicalName
var mainScope: CoroutineScope? = null
//点击间隔
private var mInterval = -1L
//点击坐标xy
private var mPointX = -1f
private var mPointY = -1f
//悬浮窗视图
private lateinit var mFloatingView: FloatingClickView
companion object {
val FLAG_ACTION = "flag_action"
//打开悬浮窗
val ACTION_SHOW = "action_show"
//⾃动点击事件开启/关闭
val ACTION_PLAY = "action_play"
val ACTION_STOP = "action_stop"
//关闭悬浮窗
val ACTION_CLOSE = "action_close"
}
override fun onCreate() {
startForegroundNotification()
mFloatingView = FloatingClickView(this)
}
val action = getStringExtra(FLAG_ACTION)
Log.d(TAG, "action " + action)
when (action) {
ACTION_SHOW -> {
mInterval = getLongExtra("interval", 5000)
mFloatingView.show()
}
ACTION_PLAY -> {
mPointX = getFloatExtra("pointX", 0f)
mPointY = getFloatExtra("pointY", 0f)
mainScope = MainScope()
autoClickView(mPointX, mPointY)
}
ACTION_STOP -> {
mainScope?.cancel()
}
ACTION_CLOSE -> {
mainScope?.cancel()
}
else -> {
Log.e(TAG, "action error")
}
}
}
StartCommand(intent, flags, startId)
}
private fun startForegroundNotification() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationBuilder =
NotificationCompat.Builder(this, NotificationConstants.CHANNEL_ID)
val notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setCategory(Notification.CATEGORY_SERVICE)
.build()
startForeground(-1, notification)
} else {
startForeground(-1, Notification())
}
}
@RequiresApi(Build.VERSION_CODES.N)
private fun autoClickView(x: Float, y: Float) {
mainScope?.launch {
while (true) {
delay(mInterval)
Log.d(TAG, "auto click x:$x  y:$y")
val path = Path()
val gestureDescription = GestureDescription.Builder()
.addStroke(GestureDescription.StrokeDescription(path, 100L, 100L))
.
build()
dispatchGesture(
gestureDescription,
object : AccessibilityService.GestureResultCallback() {
override fun onCompleted(gestureDescription: GestureDescription?) {                            Completed(gestureDescription)
Log.d(TAG, "⾃动点击完成")
}
override fun onCancelled(gestureDescription: GestureDescription?) {                            Cancelled(gestureDescription)
Log.d(TAG, "⾃动点击取消")
}
},
null
)
}
}
}
override fun onInterrupt() {
}
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
}
override fun onDestroy() {
mainScope?.cancel()
}
}
悬浮窗
SingletonHolder.kt
open class SingletonHolder<out T, in A>(creator: (A) -> T) {
private var creator: ((A) -> T)? = creator
@Volatile private var instance: T? = null
fun getInstance(arg: A): T {
val i = instance
if (i != null) {
return i
}
return synchronized(this) {
val i2 = instance
if (i2 != null) {
i2
} else {
val created = creator!!(arg)
instance = created
creator = null
created
}
}
}
}
FloatingManager.kt
t.Context
import android.view.View
import android.view.WindowManager
class FloatingManager private constructor(context: Context) {
//获得WindowManager对象
private var mWindowManager: WindowManager = SystemService(Context.WINDOW_SERVICE) as WindowManager    companion object : SingletonHolder<FloatingManager, Context>(::FloatingManager)
/**
* 添加悬浮窗
* @param view
* @param params
* @return
*/
fun addView(view: View, params: WindowManager.LayoutParams): Boolean {
try {
mWindowManager.addView(view, params)
return true
} catch (e: Exception) {
e.printStackTrace()
}
return false
}
/**
* 移除悬浮窗
*
* @param view
* @return
*/
fun removeView(view: View): Boolean {
try {
android模拟点击
return true
} catch (e: Exception) {
e.printStackTrace()
}
return false
}
/**
* 更新悬浮窗参数
*
* @param view
* @param params
* @return
*/
fun updateView(view: View, params: WindowManager.LayoutParams): Boolean {
try {
mWindowManager.updateViewLayout(view, params)
return true
} catch (e: Exception) {
e.printStackTrace()
}
return false
}
}
FloatingClickView.kt
import android.annotation.SuppressLint
t.Context
t.Intent
aphics.PixelFormat
import android.os.Build
import android.view.*
import android.widget.FrameLayout
import androidx.appcompat.widget.AppCompatImageView
class FloatingClickView(private val mContext: Context) : FrameLayout(mContext) {
private lateinit var mWindowManager: FloatingManager
private var mParams: WindowManager.LayoutParams? = null
private lateinit var mView: View
//按下坐标
private var mTouchStartX = -1f
private var mTouchStartY = -1f