【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 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 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节点下

            
                
            

            
        

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


Test
仅供学习使用,切勿乱搞,否则后果自负

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();
    }
}

布局文件




    

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

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

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

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

 

你可能感兴趣的:(#,android,从入门到项目)