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