美文网首页
AccessibilityService抢红包

AccessibilityService抢红包

作者: ukyoo | 来源:发表于2018-10-31 16:33 被阅读0次

    迫于忘记写ITP要发红包, 顺手写了个自动抢红包的demo,关于AccessibilityService的介绍如下:

    AccessibilityService作为service服务运行在后台中,通过AccessibilityEvent接收指定事件的回调。这样的事件表示用户在界面中的一些状态转换,例如:焦点改变了,一个按钮被点击,等等。这样的服务可以选择请求活动窗口的内容的能力。简单的说AccessibilityService就是一个后台监控服务,当你监控的内容发生改变时,就会调用后台服务的回调方法

    实现步骤:

    manifest中注册服务

    <service
            android:name=".DYHBService"
            android:enabled="true"
            android:exported="true"
            android:label="@string/douya_hongbao"
            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>
    

    accessibility_service_config的配置如下

    <?xml version="1.0" encoding="utf-8"?>
    <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
        android:description="@string/app_name"
        android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
        android:accessibilityFeedbackType="feedbackGeneric"
        android:accessibilityFlags="flagDefault"
        android:canRetrieveWindowContent="true"
        android:notificationTimeout="10"
        android:packageNames="com.suning.snmessenger" />
    
    • android:description :辅助功能描述
    • android:accessibilityEventTypes:辅助功能处理事件类型,一般配置为typeAllMask表示接收所有事件
    • android:packageNames :需要监听的应用包名
    • android:accessibilityFlags:辅助功能查找截点方式,一般配置为flagDefault默认方式。
    • android:accessibilityFeedbackType:反馈类型,包括声音,震动等等,一般指定GENERIC
    • android:notificationTimeout:设置同一事件响应的间隔,避免频繁的调用
    • android:canRetrieveWindowContent:是否允许辅助功能获得窗口的节点信息,配置为true

    开启辅助功能

    判断是否开启,跳转设置界面

    val isOpen = isAccessibilitySettingsOn(this, DYHBService::class.java.name)
    if (!isOpen) {
        val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
        startActivity(intent)
    }
    
    private fun isAccessibilitySettingsOn(context: Context?, className: String): Boolean {
        if (context == null) {
            return false
        }
        var accessibilityEnable: Int = 0
        val serviceName: String = context.packageName + "/" + className
        try {
            accessibilityEnable =
                    Settings.Secure.getInt(context.contentResolver, Settings.Secure.ACCESSIBILITY_ENABLED, 0)
        } catch (e: Exception) {
            Log.e("mainActivity", "get accessibility enable failed, the err:" + e.message)
        }
        if (accessibilityEnable == 1) {
            val mStringColonSplitter = SimpleStringSplitter(':')
            val settingValue =
                Settings.Secure.getString(context.contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES)
    
            if (settingValue != null) {
                mStringColonSplitter.setString(settingValue)
                while (mStringColonSplitter.hasNext()) {
                    val accessibilityService: String = mStringColonSplitter.next()
                    if (accessibilityService.equals(serviceName, true)) {
                        Log.v("mainActivity", "We've found the correct setting - accessibility is switched on!");
                        return true
                    }
                }
            }
        } else {
            Log.d("mainActivity", "Accessibility service disable")
        }
        return false
    }
    
    

    实现辅助功能的逻辑

    这里需要重写onAccessibilityEvent()方法

    • 窗口的内容出现了变化,即TYPE_WINDOW_CONTENT_CHANGED
      通过DDMS查到红包对应的resourceId, 调用performAction模拟点击红包view


    if (event.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
        val s = "xxxx" //包名
        val weikaiList: List<AccessibilityNodeInfo> =
            mRootNodeInfo!!.findAccessibilityNodeInfosByViewId("$s:id/receive")
    
        for (nodeInfo in weikaiList) {
            if (nodeInfo.text == "领取红包") {
                nodeInfo.parent.performAction(AccessibilityNodeInfo.ACTION_CLICK)
            }
        }
    }
    
    • 点击领取红包后,会弹出红包的dialog,会触发TYPE_WINDOW_CONTENT_CHANGED
      同样通过DDMS可以查到红包dialog对应的viewId, 调用performAction模拟点击红包view


    val clickedWindowList =
        mRootNodeInfo!!.findAccessibilityNodeInfosByViewId("$s:id/redpackets_open")
    if (clickedWindowList.size > 0) {
        val curNodeInfo1 = clickedWindowList[0]
        curNodeInfo1.performAction(AccessibilityNodeInfo.ACTION_CLICK)
    }
    
    • 领取红包后, 会跳到红包的领取详情界面,会触发TYPE_WINDOW_STATE_CHANGED
      同样调用performAction模拟点击箭头退出页面, 回到主页面继续抢红包
    val backlist =
        mRootNodeInfo!!.findAccessibilityNodeInfosByViewId("$s:id/back_btn")
    if (backlist.size > 0) {
        val curNodeInfo1 = backlist[0]
        curNodeInfo1.performAction(AccessibilityNodeInfo.ACTION_CLICK)
    }
    

    相关文章

      网友评论

          本文标题:AccessibilityService抢红包

          本文链接:https://www.haomeiwen.com/subject/sauatqtx.html