android apk实现uiautomator脚本的运行

作者: 早起有虫吃 | 来源:发表于2017-09-13 10:20 被阅读1659次

脚本的运行有有多种方式,可以辅助调试类运行,可以命令行运行,也可以工具直接运行今天我们来聊聊如何用android apk实现脚本的运行,以下的方式只针对于手机已经获取root权限的情况,首先我们先分析下原理:
用android studio右击run运行脚本,在控制台中会出现如下信息:

image.png

下面是详细的步骤及代码:

1.build.gradle文件中添加依赖,并同步

添加入依赖如下:

androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.0'
    compile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.0'

附图如下:


image.png

2.然后进行同步

3.布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"


    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击打开QQ"
        android:gravity="center"
        android:id="@+id/button_1"/>


</LinearLayout>

4.测试类代码如下目录

image.png

代码是启动qq的示例,具体的操作根据需要自行编写,示例代码如下

package com.example.administrator.excutescript;

import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.UiAutomatorTestCase;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiSelector;

import org.junit.Test;

/**
 * Created by Administrator on 2017/9/13.
 */

public class OpenQQ  extends UiAutomatorTestCase{
    @Test
    public void  test() throws UiObjectNotFoundException {
      //以下是uiautomator1的打开qq方式
        /*  getUiDevice();
        UiObject qq=new UiObject(new UiSelector().text("QQ"));
        qq.click();*/


        //以下是uiautomator2的打开qq方式
        UiDevice uiDevice;
        uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
        uiDevice.pressHome();
        UiObject qq=uiDevice.findObject(new UiSelector().text("QQ"));
        qq.click();


    }
}

5.MainActivity代码如下

package com.example.administrator.excutescript;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    //声明Button按钮
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //找到button控件
        button=(Button) findViewById(R.id.button_1);

        //对button实现点击监控,由于是耗时操作,需要另起线程
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new OpenQQ().start();
            }
        });
    }

    class OpenQQ extends Thread{
        @Override
        public void run() {
            //class后的参数是包名+类名
            ShellUtils.execCommand("am instrument -w -r   -e debug false -e class com.example.administrator.excutescript.OpenQQ com.example.administrator.excutescript.test/android.support.test.runner.AndroidJUnitRunner",true);

        }
    }
}

6.工具类代码如下:

package com.example.administrator.excutescript;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;

/**
 * Created by Administrator on 2017/7/13.
 * 有效启动shell类
 */

public class ShellUtils {

    public static final String COMMAND_SU       = "su";
    public static final String COMMAND_SH       = "sh";
    public static final String COMMAND_EXIT     = "exit\n";
    public static final String COMMAND_LINE_END = "\n";

    private ShellUtils() {
        throw new AssertionError();
    }

    /**
     * check whether has root permission
     *
     * @return
     */
    public static boolean checkRootPermission() {
        return execCommand("echo root", true, false).result == 0;
    }

    /**
     * execute shell command, default return result msg
     *
     * @param command command
     * @param isRoot whether need to run with root
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(String command, boolean isRoot) {
        return execCommand(new String[] {command}, isRoot, true);
    }

    /**
     * execute shell commands, default return result msg
     *
     * @param commands command list
     * @param isRoot whether need to run with root
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(List<String> commands, boolean isRoot) {
        return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, true);
    }

    /**
     * execute shell commands, default return result msg
     *
     * @param commands command array
     * @param isRoot whether need to run with root
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(String[] commands, boolean isRoot) {
        return execCommand(commands, isRoot, true);
    }

    /**
     * execute shell command
     *
     * @param command command
     * @param isRoot whether need to run with root
     * @param isNeedResultMsg whether need result msg
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) {
        return execCommand(new String[] {command}, isRoot, isNeedResultMsg);
    }

    /**
     * execute shell commands
     *
     * @param commands command list
     * @param isRoot whether need to run with root
     * @param isNeedResultMsg whether need result msg
     * @return
     * @see ShellUtils#execCommand(String[], boolean, boolean)
     */
    public static CommandResult execCommand(List<String> commands, boolean isRoot, boolean isNeedResultMsg) {
        return execCommand(commands == null ? null : commands.toArray(new String[] {}), isRoot, isNeedResultMsg);
    }

    /**
     * execute shell commands
     *
     * @param commands command array
     * @param isRoot whether need to run with root
     * @param isNeedResultMsg whether need result msg
     * @return <ul>
     *         <li>if isNeedResultMsg is false, {@link CommandResult#successMsg} is null and
     *         {@link CommandResult#errorMsg} is null.</li>
     *         <li>if {@link CommandResult#result} is -1, there maybe some excepiton.</li>
     *         </ul>
     */
    public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) {
        int result = -1;
        if (commands == null || commands.length == 0) {
            return new CommandResult(result, null, null);
        }

        Process process = null;
        BufferedReader successResult = null;
        BufferedReader errorResult = null;
        StringBuilder successMsg = null;
        StringBuilder errorMsg = null;

        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
            os = new DataOutputStream(process.getOutputStream());
            for (String command : commands) {
                if (command == null) {
                    continue;
                }

                // donnot use os.writeBytes(commmand), avoid chinese charset error
                os.write(command.getBytes());
                os.writeBytes(COMMAND_LINE_END);
                os.flush();
            }
            os.writeBytes(COMMAND_EXIT);
            os.flush();

            result = process.waitFor();
            // get command result
            if (isNeedResultMsg) {
                successMsg = new StringBuilder();
                errorMsg = new StringBuilder();
                successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
                errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                String s;
                while ((s = successResult.readLine()) != null) {
                    successMsg.append(s);
                }
                while ((s = errorResult.readLine()) != null) {
                    errorMsg.append(s);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (successResult != null) {
                    successResult.close();
                }
                if (errorResult != null) {
                    errorResult.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (process != null) {
                process.destroy();
            }
        }
        return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null
                : errorMsg.toString());
    }

    /**
     * result of command
     * <ul>
     * <li>{@link CommandResult#result} means result of command, 0 means normal, else means error, same to excute in
     * linux shell</li>
     * <li>{@link CommandResult#successMsg} means success message of command result</li>
     * <li>{@link CommandResult#errorMsg} means error message of command result</li>
     * </ul>
     *
     * @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-5-16
     */
    public static class CommandResult {

        /** result of command **/
        public int    result;

        /** success message of command result **/
        public String successMsg;

        /** error message of command result **/
        public String errorMsg;

        public CommandResult(int result) {
            this.result = result;
        }

        public CommandResult(int result, String successMsg, String errorMsg) {
            this.result = result;
            this.successMsg = successMsg;
            this.errorMsg = errorMsg;
        }
    }
}


注意点:在apk启动前,必须保证脚本已经在手机中,且手机授权root

相关文章

网友评论

  • af252b5fa108:您好 我试图重现效果,但是点击按钮出现Unable to find instrumentation info for: ComponentInfo{}异常,3505722960 这是我的qq,能加好友指点一下吗?感激不尽!
  • 854825b03835:你好,除了root外,apk不需要进行系统签名吗
    Tevins:你好,关于测试类代码执行,有点问题想跟你请教一下,不知是否方便加一个qq:1913739434
    854825b03835:@早起有虫吃 你好,我qq 1007642017,方便的话加你一下,咨询你这个帖子的问题
    早起有虫吃:对的,root就可以了

本文标题:android apk实现uiautomator脚本的运行

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