Android基于Android Studio的测试研究自动点击实现解锁然后进入计算器输入我的QQ号码,编写外挂如此简单

学完本篇文章,你会感觉你很想写自动点击方式的外挂了,就是这么爽,这么简单
,锁屏 点击 都那么easy.



dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'//最新sdk18
}

简单的测试模板代码

package cn.qssq666.androidtest;

import android.app.Instrumentation;
import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.util.Log;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * Created by qssq on 2018/6/10 qssq666@foxmail.com
 */
@RunWith(AndroidJUnit4.class)
public class QssqTest {


    private static final String TAG = "QssqTest";
    Instrumentation mInstrumentation;
    UiDevice mUiDevice;

    @Before
    public  void before(){

        mInstrumentation=InstrumentationRegistry.getInstrumentation();
        mUiDevice=UiDevice.getInstance(mInstrumentation);

        Log.w(TAG,"BEFORE RUN");
    }
@Test
    public void pressKey() throws RemoteException {

        mUiDevice.pressRecentApps();

    }


}

界面特征 破解语音红包也可以用这些思路,甚至根据标题大小,控件类型也可以.

介绍By类的用法

by类有如下经典的查找匹配方法


image.png

玩耍uiautomatorviewer

那么如何获取id呢,当然使用uiautomatorviewer啦!
获取id的方法

aaadeMBP:AndroidTest aaa$ cd $ANDROID_SDK_HOME/tools/bin
aaadeMBP:bin aaa$ ls
apkanalyzer             avdmanager              lint                    screenshot2             uiautomatorviewer
archquery               jobb                    monkeyrunner            sdkmanager

进入环境变量目录查看uiautomatorviewer文件,那么就启动它了.

image.png

image.png

系统通常是这样的android:id/text1 xml里面这是@android:id/text1 那么正常的是这样的
cn.qssq666.androidtest:id/tv_1而xml里面是这样的.@+id/tv_1
ok,讲解完毕开始上手按键的查找点击了. 因为按键查找实际上就是取的uiautomatorviewer里面id的字符串.

By.res的多个参数说明
根据原理可以的出来,一个参数是包含了:id,分割开的话就只要资源名称和包名.不过为了方便通常是用这个工具获取所有全名称了.

   */
    public BySelector res(String resourcePackage, String resourceId) {
        checkNotNull(resourcePackage, "resourcePackage cannot be null");
        checkNotNull(resourceId, "resourceId cannot be null");

        return res(Pattern.compile(Pattern.quote(
                String.format("%s:id/%s", resourcePackage, resourceId))));
    }

quote的意思就是把里面可能存在的正则自动转义,亏我以前手写,原来有这么简单的方式.

高级功能

image.png

image.png

实战代码

进入编辑短信界面 确保2个输入框都同时存在

这里演示使用原生模拟器


image.png

下面的话的意思是获取获取了焦点的编辑框,然后输入一些内容而且这内容会把之前的内容


    @Test
    public void testSms() {

        BySelector focused = By.focused(true);
        UiObject2 object = mUiDevice.findObject(focused);
        if (object == null) {
            throw new RuntimeException("当前界面没有空间获取到了焦点");
        } else {
//            object.click();//编辑框点击会弹出一个菜单,导致之后的逻辑无法正常执行抛出异常
            String text = object.getText();
            String className = object.getClassName();
            Log.w(TAG, "当前text:" + text + "," + className);
            object.setText("我插入了你,beflore:" + text + ",className:" + className);//StaleObjectException
        }

    }

进入计算器界面输入数字

@Test
    public void findView() {
        //android:id/text1
       /* BySelector bySelector = By.res("cn.qssq666.androidtest:id/text1");
        System.out.println("bySelector:"+bySelector);
        //        BySelector bySelector = By.res("android:id/text1");
        mUiDevice.findObject(bySelector).setText("我修改了android:text1");

*/

        UiObject2 object = mUiDevice.findObject(By.res("com.android.calculator2:id/digit_7"));
        if (object != null) {
            object.setText("修改");//修改是无效的
            object.click();

            UiObject2 object1 = mUiDevice.findObject(By.text("0"));
            object1.click();

            mUiDevice.findObject(By.desc("加")).click();
            mUiDevice.findObject(By.text("3")).click();
            mUiDevice.findObject(By.text("5")).click();
            mUiDevice.findObject(By.text("0")).click();
            mUiDevice.findObject(By.text("6")).click();
            mUiDevice.findObject(By.text("8")).click();
            mUiDevice.findObject(By.text("2")).click();
            mUiDevice.findObject(By.text("6")).click();
            mUiDevice.findObject(By.text("4")).click();

        } else {
            Log.e(TAG, "没有打开计算器!");
        }


        BySelector bySelector1 = By.res(BuildConfig.APPLICATION_ID, "text1");
        UiObject2 object1 = mUiDevice.findObject(bySelector1);
        if (object1 != null) {
            object1.setText("我修改了当前包名text1");

        } else {
            Log.w(TAG, "没有找到是否运行了" + BuildConfig.APPLICATION_ID + "呢!");
        }
    }
image.png

高级实战编写完整业务逻辑

我要做的就是在任意界面执行这段代码就可以实现锁屏然后解锁然后找到计算器应用然后滑动打开菜单输入根号然后关闭菜单输入我的数字得到我的QQ号码

 @Test
    public void fromLockScreenEnterCalc() throws RemoteException {
        //滑动解锁,->点击计算器应用->滑动按下根号,然后按下 9
        if (mUiDevice.isScreenOn()) {//没有锁屏那么就进行锁屏呗

//        int x=528;//
            mUiDevice.pressKeyCode(KeyEvent.KEYCODE_BACK);
            mUiDevice.pressKeyCode(KeyEvent.KEYCODE_HOME);
            mUiDevice.pressKeyCode(KeyEvent.KEYCODE_POWER);//回到home页,然后锁屏,
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        } else {
            mUiDevice.pressKeyCode(KeyEvent.KEYCODE_HOME);
        }

        //亮屏

        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_POWER);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        int step = 200 / 10;

        int x = 1080 / 2;//
        //解锁屏幕 从屏幕底部往上面0坐标滑动
        mUiDevice.swipe(x, 1080, x, 0, step);


        UiObject2 calc = mUiDevice.findObject(By.desc("计算器"));

        if (calc == null) {
            //锁屏了还需要做一个操作,就是点击一个图标向上的箭头
            UiObject2 current = mUiDevice.findObject(By.text("应用列表"));
            if (current == null) {
                current = mUiDevice.findObject(By.res("com.google.android.apps.nexuslauncher:id/all_apps_handle"));
                //com.google.android.apps.nexuslauncher:id/all_apps_handle
                if (current == null) {
                    throw new RuntimeException("找不到计算器也找不到展开所有应用的图标按钮");
                }
            }


            current.click();
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {

                e.printStackTrace();
            }


            calc = mUiDevice.findObject(By.desc("计算器"));
            if (calc == null) {
                throw new RuntimeException("找不到计算器");
            }

        }


        calc.click();
        try {
            Thread.sleep(1500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        mUiDevice.swipe(1080 - 5, 1285, 8, 1285, 500 / 10);//steps 可能是1秒


        UiObject2 object = mUiDevice.findObject(By.res("com.android.calculator2:id/op_add"));
        if (object == null) {
            object = object.findObject(By.text("√)"));

        }
        if (object == null) {
            throw new RuntimeException("抱歉,找不到开根号按钮");
        }
        object.click();


        //按返回键关闭根号菜单
        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_BACK);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

//        mUiDevice.pressKeyCode(KeyEvent.KEYCODE_9);

        pressMulti("9");
        pressMulti("=");
        pressMulti("+");
        pressMulti("3");
        pressMulti("5");
        pressMulti("0");
        pressMulti("6");
        pressMulti("8");
        pressMulti("2");
        pressMulti("6");
        pressMulti("1");
        pressMulti("=");

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();

        }

         object = mUiDevice.findObject(By.res("com.android.calculator2:id/result"));
        if(object==null){
            object=mUiDevice.findObject(By.text("35068264"));
        }
        if(object==null){
            throw new RuntimeException("无法得知结果");
        }
        String str=object.getText();
        assertEquals(str,"35068264");

    }

    private void pressMulti(String s) {


        UiObject2 object = mUiDevice.findObject(By.text(s));
        if (object == null) {
            throw new RuntimeException("找不到按键" + s);
        } else {
            object.click();
        }
    }

最后的结果就是我的qq

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,969评论 3 119
  • 昨天经过一家店门口,听到了陈奕迅的《最佳损友》。 被里面的好多歌词感动,好久没有什么东西能真正触动我了。 回到家又...
    黎小蛮阅读 208评论 0 1
  • 最近爱上了用vue.js做前端,昨天用vue上传图片时遇到了问题,最后半天时间终于摸索出来,我将相关部分的代码贴出...
    童蒙vlog阅读 8,012评论 3 18
  • 感恩!同事帮忙分析预计完成与实际完成差异及原因。谢谢!谢谢!谢谢! 感恩!女儿帮忙买电和气,我省心了。谢谢!谢谢!...
    梧桐70阅读 236评论 0 0
  • 为了追上那个曾经被寄予厚望的自己 女:这是我从小到大生活的地方,这里的生活很简单,平淡又自由,没有太多的意外和惊...
    韩玲Julie阅读 1,137评论 0 0