Android实现自动点击

您所在的位置:网站首页 手机自动点击器怎么关闭 Android实现自动点击

Android实现自动点击

2023-05-22 12:50| 来源: 网络整理| 查看: 265

ps: 不想看代码的滑到最下面有apk包百度网盘下载地址

1. 先看效果图 不然都是耍流氓

2.项目目录

 

3.一些配置

build.gradle

plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-android-extensions' } android { compileSdkVersion 31 buildToolsVersion "30.0.3" defaultConfig { applicationId "com.znan.autoclick" minSdkVersion 24 targetSdkVersion 31 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), '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 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.3.0' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.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" }

accessibility.xml

AndroidManifest.xml 注册权限和服务

4.代码

AutoClickService.kt 无障碍服务

class AutoClickService : AccessibilityService() { private val TAG = javaClass.canonicalName var mainScope: CoroutineScope? = null private val broadcastReceiver = BroadcastHandler(this) //点击间隔 private var mInterval = -1L //点击坐标xy private var mPointX = -1f private var mPointY = -1f //悬浮窗视图 private lateinit var mFloatingView: FloatingClickView companion object { //打开悬浮窗 val ACTION_SHOW = "action_show" //自动点击事件 开启/关闭 val ACTION_PLAY = "action_play" val ACTION_STOP = "action_stop" //关闭悬浮窗 val ACTION_CLOSE = "action_close" } private inner class BroadcastHandler(val context: Context) : BroadcastReceiver() { fun register() { context.registerReceiver( this, IntentFilter().apply { addAction(BroadcastConstants.BROADCAST_ACTION_AUTO_CLICK) //息屏关闭自动点击事件 addAction(Intent.ACTION_SCREEN_OFF) } ) } fun unregister() { context.unregisterReceiver(this) } override fun onReceive(p0: Context?, intent: Intent?) { intent?.apply { when(action) { Intent.ACTION_SCREEN_OFF -> { mFloatingView.remove() mainScope?.cancel() } BroadcastConstants.BROADCAST_ACTION_AUTO_CLICK -> { when (getStringExtra(BroadcastConstants.KEY_ACTION)) { ACTION_SHOW -> { mFloatingView.remove() mainScope?.cancel() mInterval = getLongExtra(BroadcastConstants.KEY_INTERVAL, 5000) mFloatingView.show() } ACTION_PLAY -> { mPointX = getFloatExtra(BroadcastConstants.KEY_POINT_X, 0f) mPointY = getFloatExtra(BroadcastConstants.KEY_POINT_Y, 0f) mainScope = MainScope() autoClickView(mPointX, mPointY) } ACTION_STOP -> { mainScope?.cancel() } ACTION_CLOSE -> { mFloatingView.remove() mainScope?.cancel() } else -> { Log.e(TAG, "action error") } } } } } } } override fun onCreate() { super.onCreate() startForegroundNotification() mFloatingView = FloatingClickView(this) broadcastReceiver.register() } 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() path.moveTo(x, y) val gestureDescription = GestureDescription.Builder() .addStroke(GestureDescription.StrokeDescription(path, 100L, 100L)) .build() dispatchGesture( gestureDescription, object : AccessibilityService.GestureResultCallback() { override fun onCompleted(gestureDescription: GestureDescription?) { super.onCompleted(gestureDescription) Log.d(TAG, "自动点击完成") } override fun onCancelled(gestureDescription: GestureDescription?) { super.onCancelled(gestureDescription) Log.d(TAG, "自动点击取消") } }, null ) } } } override fun onInterrupt() { } override fun onAccessibilityEvent(event: AccessibilityEvent?) { } override fun onDestroy() { super.onDestroy() broadcastReceiver.unregister() mainScope?.cancel() } }

悬浮窗

SingletonHolder.kt

open class SingletonHolder(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

import android.content.Context import android.view.View import android.view.WindowManager class FloatingManager private constructor(context: Context) { //获得WindowManager对象 private var mWindowManager: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager companion object : SingletonHolder(::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 { mWindowManager.removeView(view) 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

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 val STATE_CLICKING = "state_clicking" val STATE_NORMAL = "state_normal" private var mCurrentState = STATE_NORMAL private var ivIcon: AppCompatImageView? = null init { initView() } private fun initView() { mView = LayoutInflater.from(context).inflate(R.layout.view_floating_click, null) ivIcon = mView.findViewById(R.id.iv_icon) mWindowManager = FloatingManager.getInstance(mContext) initListener() } @SuppressLint("ClickableViewAccessibility") private fun initListener() { mView.setOnTouchListener { v, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { mTouchStartX = event.rawX mTouchStartY = event.rawY } MotionEvent.ACTION_MOVE -> { mParams?.let { it.x += (event.rawX - mTouchStartX).toInt() it.y += (event.rawY - mTouchStartY).toInt() mWindowManager.updateView(mView, it) } mTouchStartX = event.rawX mTouchStartY = event.rawY } } false } mView.setOnClickListener { val location = IntArray(2) it.getLocationOnScreen(location) val intent = Intent().apply { action = BroadcastConstants.BROADCAST_ACTION_AUTO_CLICK when (mCurrentState) { STATE_NORMAL -> { mCurrentState = STATE_CLICKING putExtra(BroadcastConstants.KEY_ACTION, AutoClickService.ACTION_PLAY) putExtra(BroadcastConstants.KEY_POINT_X, (location[0] - 1).toFloat()) putExtra(BroadcastConstants.KEY_POINT_Y, (location[1] - 1).toFloat()) ivIcon?.setImageResource(R.drawable.ic_auto_click_icon_green_24) } STATE_CLICKING -> { mCurrentState = STATE_NORMAL putExtra(BroadcastConstants.KEY_ACTION, AutoClickService.ACTION_STOP) ivIcon?.setImageResource(R.drawable.ic_auto_click_icon_gray_24) } } } context.sendBroadcast(intent) } } fun show() { mParams = WindowManager.LayoutParams() mParams?.apply { gravity = Gravity.CENTER //总是出现在应用程序窗口之上 type = if (Build.VERSION.SDK_INT >= 26) { WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY } else { WindowManager.LayoutParams.TYPE_SYSTEM_ALERT } //设置图片格式,效果为背景透明 format = PixelFormat.RGBA_8888 flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH width = LayoutParams.WRAP_CONTENT height = LayoutParams.WRAP_CONTENT if (mView.isAttachedToWindow) { mWindowManager.removeView(mView) } mWindowManager.addView(mView, this) } } fun remove() { mCurrentState = STATE_NORMAL ivIcon?.setImageResource(R.drawable.ic_auto_click_icon_gray_24) mWindowManager.removeView(mView) } }

页面事件

MainActivity.kt

class MainActivity : AppCompatActivity() { private val TAG = javaClass::class.java.canonicalName override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initNotification() initListener() startAutoClickService() } private fun initListener() { btn_accessibility.setOnClickListener { checkAccessibility() } btn_floating_window.setOnClickListener { checkFloatingWindow() } btn_show_window.setOnClickListener { hideKeyboard() if (TextUtils.isEmpty(et_interval.text.toString())) { Snackbar.make(et_interval, "请输入间隔", Snackbar.LENGTH_SHORT).show() return@setOnClickListener } showFloatingWindow(et_interval.text.toString().toLong()) } btn_close_window.setOnClickListener { closeFloatWindow() } btn_test.setOnClickListener { Log.d(TAG, "btn_test on click") } } /** * 跳转设置开启无障碍 */ private fun checkAccessibility() { val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS) startActivity(intent) } /** * 跳转设置顶层悬浮窗 */ private fun checkFloatingWindow() { if (Build.VERSION.SDK_INT >= 23) { if (Settings.canDrawOverlays(this)) { Toast.makeText(this, "已开启", Toast.LENGTH_SHORT).show() } else { val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION) startActivity(intent) } } } private fun startAutoClickService() { val intent = Intent(this, AutoClickService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(intent) } else { startService(intent) } } private fun showFloatingWindow(interval: Long) { sendBroadcast(Intent().apply { action = BroadcastConstants.BROADCAST_ACTION_AUTO_CLICK putExtra(BroadcastConstants.KEY_ACTION, AutoClickService.ACTION_SHOW) putExtra(BroadcastConstants.KEY_INTERVAL, interval) }) } private fun closeFloatWindow() { sendBroadcast(Intent().apply { action = BroadcastConstants.BROADCAST_ACTION_AUTO_CLICK putExtra(BroadcastConstants.KEY_ACTION, AutoClickService.ACTION_CLOSE) }) } private fun initNotification() { //注册渠道id if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val name = NotificationConstants.CHANNEl_NAME val descriptionText = NotificationConstants.CHANNEL_DES val importance = NotificationManager.IMPORTANCE_DEFAULT val channel = NotificationChannel(NotificationConstants.CHANNEL_ID, name, importance).apply { description = descriptionText } channel.enableLights(true) channel.lightColor = Color.GREEN // Register the channel with the system val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.createNotificationChannel(channel) } } override fun onDestroy() { val intent = Intent(this, AutoClickService::class.java) stopService(intent) super.onDestroy() } //收起输入法 fun hideKeyboard() { val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager if (imm.isActive && currentFocus != null) { imm.hideSoftInputFromWindow( currentFocus!!.windowToken, InputMethodManager.HIDE_NOT_ALWAYS ) } } } object NotificationConstants { val CHANNEL_ID = "auto_channel_id" val CHANNEl_NAME = "Auto Click" val CHANNEL_DES = "Auto Click Service" } object BroadcastConstants { val BROADCAST_ACTION_AUTO_CLICK = "BROADCAST_ACTION_AUTO_CLICK" val KEY_ACTION = "KEY_ACTION" val KEY_INTERVAL = "KEY_INTERVAL" val KEY_POINT_X = "KEY_POINT_X" val KEY_POINT_Y = "KEY_POINT_Y" }

5.布局

6.app-auto-click.zip

百度网盘

 提取码: 6p2u 

 告辞~



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3