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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

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