【10】AccessibilityService实现探探app的自动化喜欢和不喜欢+ [as 3.0如何打开层级调用uiautomatorviewer]

目前版本3.1.8  仅供学习使用!!!!!切勿用作非法用途,否则后果自负!

直接写这个东西 可能是有些唐突

因为你们可能不知道这是一个什么玩意 如果你想看过于这个Accessibility服务的一些资料

可以到 我的分类 下面去看

下面将直接进入正题

AccessibilityService 的出现原本为了帮助盲人 来那啥那啥和那啥的

没想到却被我们那啥那啥和那啥了

他使用方法需要手动到无障碍里面去开启 开启成功以后代码就开始运行了

集成的一般步骤就是

创建服务 继承AccessibilityService实现相关方法

package com.example.liuan.test;

import android.accessibilityservice.AccessibilityService;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;

import java.io.DataOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Random;


public class MyService extends AccessibilityService {
    private static final String TAG = "MyService";
    // 大多数的手机包名一样,联想部分机型的手机不一样
    private String[] packageNames = {"com.p1.mobile.putong"};
    int startFlag = 0;

    AccessibilityNodeInfo[] noteInfo = new AccessibilityNodeInfo[2];



    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (event.getSource() != null) {
            findNodesByText(event, "继续探索");
        }

        switch (event.getEventType()) {
            case AccessibilityEvent.TYPE_VIEW_CLICKED:

                if (SpUtils.getBoolean(this, "reSet", false)) {
                    SpUtils.putBoolean(this, "reSet", false);
                    startFlag = 0;
                }

                if (startFlag == 0) {
                    //记录正确
                    startFlag = 1;
                    noteInfo[0] = event.getSource();
                } else if (startFlag == 1) {
                    //记录错误  只记录一次即可
                    startFlag = 2;
                    noteInfo[1] = event.getSource();
                }

                if (startFlag == 2) {
                    autoClick();
                }


                break;


        }

    }

    private void autoClick() {
        try {
            String time = SpUtils.getString(this, "time", "1000");
            Thread.sleep(Integer.parseInt(time));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String time = SpUtils.getString(this, "like", "50");
        int percent = Integer.parseInt(time);
//随机数字 是1-100
        int random = new Random().nextInt(100) + 1;
//如果设置了百分之50  那么就是各一半
//如果设置了百分之10  那么就是点第一个 8   10
        Log.e(TAG, "onAccessibilityEvent:random " + random);
        Log.e(TAG, "onAccessibilityEvent:percent " + percent);
        if (random <= percent) {
            //第一次按键
            noteInfo[0].performAction(AccessibilityNodeInfo.ACTION_CLICK);
        } else {
            noteInfo[1].performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }

    }


    @Override
    public void onInterrupt() {
        startFlag = 0;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        startFlag = 0;
    }

    private void findNodesByText(AccessibilityEvent event, String text) {
        List<AccessibilityNodeInfo> nodes = event.getSource().findAccessibilityNodeInfosByText(text);

        if (nodes != null && !nodes.isEmpty()) {
            for (AccessibilityNodeInfo info : nodes) {
                if (info.isClickable()) {// 只有根据节点信息是下一步,安装,完成,打开,且是可以点击的时候,才执行后面的点击操作
                    if ("继续探索".equals(text)) {
                        info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    }
                }
            }
        }
    }

    private boolean isTextExist(AccessibilityEvent event, String text) {
        List<AccessibilityNodeInfo> nodes = event.getSource().findAccessibilityNodeInfosByText(text);

        if (nodes != null && !nodes.isEmpty()) {
            for (AccessibilityNodeInfo info : nodes) {
                if (info.isClickable()) {// 只有根据节点信息是下一步,安装,完成,打开,且是可以点击的时候,才执行后面的点击操作
                    if ("继续探索".equals(text)) {
                        return true;
                    }
                }
            }
        }
        return false;

    }

}

我的思路 我简单来说一下 因为就算你层级用的没问题 但是却获取不到id

我就急中生智 使用了event.getSource() 把这个保存到数组 让自己点两下 然后开始模仿我的点击

这个方法不仅仅使用与这里 可以用作好多的地方 

AccessiblityServices 要比脚本稳定 脚本存在一种情况就是脚本会崩溃 或者由于某个地方的偏移导致点击错误

这个从节点点击 彻底的解决了这个问题 无论开发者怎么骚操作 这里都可以点击 好气的

获取那个文件的id 或者文字什么的 用到了studio工具中的(本文代码风骚 没有用到这个)

G:\android\sdk\tools\bin\uiautomatorviewer.bat

as 3.0居然丧尽天良把他搞没了 反正我没找到 可能是没了

只能去sdk 目录下去找了 如果你记忆力够好的话找到你曾经安装的sdk目录

如果记忆力不够好 可以在alt+ctrl+s System Settings-->Android SDK看到你的sdk目录 找到打开即可

具体使用方法这里不做教程

四大组件逃不过的清单文件

application节点下
<service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"
            android: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>

res/xml/accessibility.xml 没有这个目录请自行创建

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"
    android:description="@string/des"
    android:notificationTimeout="100"
    android:packageNames="com.p1.mobile.putong" />
<resources>
<string name="app_name">Test</string>
<string name="des">仅供学习使用,切勿乱搞,否则后果自负</string>
</resources>

MainActivity

package com.example.liuan.test;

import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "MainActivity";
    private Button mBtOpen;
    private EditText mEtDelay;
    private EditText mEtLike;
    /**
     * 保存配置
     */
    private Button mBtReset;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//        String apkRoot="chmod 777 "+getPackageCodePath();
//
//        SystemManager.RootCommand(apkRoot);
        initView();
        initData();

    }

    private void initData() {
        SpUtils.putString(this, "time", mEtDelay.getText().toString().trim());
        SpUtils.putString(this, "like", mEtLike.getText().toString().trim());
        SpUtils.putBoolean(MainActivity.this, "reSet", true);
    }


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        Toast.makeText(MainActivity.this, "半径", Toast.LENGTH_LONG);
        switch (keyCode) {

            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_UP:
                Toast.makeText(MainActivity.this, "半径", Toast.LENGTH_LONG);
                mBtOpen.setText("已经关闭");
                return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    private void initView() {
        mBtOpen = (Button) findViewById(R.id.bt_open);
        mBtOpen.setOnClickListener(this);

        mEtDelay = (EditText) findViewById(R.id.et_delay);
        mEtLike = (EditText) findViewById(R.id.et_like);
        mEtLike.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                initData();

            }
        });
        mEtDelay.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                initData();
            }
        });

        mBtReset = (Button) findViewById(R.id.bt_reset);
        mBtReset.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            default:
                break;
            case R.id.bt_open:
                initData();
                Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
                startActivity(intent);
                break;

            case R.id.bt_reset:
                initData();
                break;
        }
    }
}

SpUtils

package com.example.liuan.test;

import android.content.Context;
import android.content.SharedPreferences;

/**
 * Created by liuan on 2018-04-28.
 */

public class SpUtils {
    private static SharedPreferences sp;
    public  static void getSharedPreference(Context context){
        if(sp==null){
            sp=context.getSharedPreferences("config",context.MODE_PRIVATE);
        }
    }
    public static void putString(Context context,String key,String value){
        getSharedPreference(context);
        sp.edit().putString(key,value).commit();
    }
    public static String getString(Context context,String key,String defValue){
        getSharedPreference(context);
       return sp.getString(key,defValue);
    }
    public static boolean getBoolean(Context context,String key,boolean defValue){
        getSharedPreference(context);
        return sp.getBoolean(key,false);
    }

    public static void putBoolean(Context context,String key,boolean value){
        getSharedPreference(context);
        sp.edit().putBoolean(key,value).commit();
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/bt_open"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开启/关闭服务" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/bt_reset"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="保存配置" />


    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="60sp"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="延时:s"
            android:textColor="@android:color/holo_red_dark" />

        <EditText
            android:id="@+id/et_delay"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:inputType="number"
            android:text="6000" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">

        <TextView

            android:layout_width="60sp"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="喜欢:x/%"
            android:textColor="@android:color/holo_red_dark" />

        <EditText
            android:id="@+id/et_like"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:inputType="number"
            android:text="94" />
    </LinearLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
    android:layout_gravity="center"
        android:gravity="center"
        android:text="本软件仅供学习使用~!!!!\n开启服务 点击一个喜欢  再点击一个不喜欢 就开始了,如果点击喜欢 出现了继续探索,要进主页点重新设置 再点击 喜欢 和不喜欢~"
        android:textColor="@android:color/holo_red_dark"
        android:textSize="22sp" />
</LinearLayout>

开始方法 并不是直接点开启就开启了

第一步 开启探探点击的服务

第二步 打开探探先把其他的第一次引导的东西点完 然后 点一个喜欢 点一个不喜欢  再然后就能看到神奇的自动了

那天我本来想写了按音量键暂停的方法  后来发现没必要 暂停服务就行了 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

安果移不动

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

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

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

打赏作者

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

抵扣说明:

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

余额充值