Monkey可视化工具开发(android篇

前几天分享了pc端的monkey可视化工具,今天来分享一下如何用android实现monkey的运行,原理是执行shell命令,各种传参,该工具需要root授权

先附上两个效果图:



以下为代码:

1.MainActivity代码如下

package com.example.administrator.monkeyshareblog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity {
    Button button,button1;
    EditText editText1,editText2,editText3,editText4,editText5,editText6,editText7;
    TextView button_package;
    private Handler handler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();
        setContentView(R.layout.activity_main);
        initView();
        Bundle bundle=getIntent().getExtras();
        try{

            String str = bundle.getString("packagename");

            Log.i("packagew",str);
            button_package.setText(str);
        }catch (NullPointerException e){
            String text = "选择一个应用";
            button_package.setText(text);
        }

        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this,NewActivity.class);
                startActivity(intent);
            }
        });

        //点击跳转到包选择界面
        button_package.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //ShowChoise();
                Intent intent = new Intent(MainActivity.this,PackageManageActivity.class);
                startActivity(intent);

            }
        });
        String times=editText6.getText().toString();
        Log.i("111",times+"==========");

        //执行monkey按钮
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new MonkeyThread().start();

            }
        });
    }
//初始化控件
    private void initView() {
        button= (Button) findViewById(R.id.button);
        button1=(Button)findViewById(R.id.button1);
        editText1= (EditText) findViewById(R.id.ed_1);
        editText2= (EditText) findViewById(R.id.ed_2);
        editText3=(EditText)findViewById(R.id.ed_3);
        editText4=(EditText)findViewById(R.id.ed_4);
        editText5=(EditText)findViewById(R.id.ed_5);
        editText6=(EditText)findViewById(R.id.ed_6);
        editText7=(EditText)findViewById(R.id.ed_7);
        button_package=(TextView) findViewById(R.id.button_package);

    }

    //monkey执行线程
    class MonkeyThread extends Thread{
        @Override
        public void run() {
            super.run();
            String swipePercent = editText1.getText().toString();
            String clickPrcent = editText2.getText().toString();
            String systemClickPercent = editText3.getText().toString();
            String startActivityPercent = editText4.getText().toString();
            String seedNum = editText5.getText().toString();
            String delayTime = editText6.getText().toString();
            String times = editText7.getText().toString();
             if (swipePercent.equals("") == false) {
                swipePercent = " --pct-motion " + swipePercent;
            } else {
                swipePercent = "";
            }
            if (clickPrcent.equals("") == false) {
                clickPrcent = " --pct-touch " + clickPrcent;
            } else {
                clickPrcent = "";
            }
            if (systemClickPercent.equals("") == false) {
                systemClickPercent = "  --pct-syskeys " + systemClickPercent;
            } else {
                systemClickPercent = "";
            }
            if (startActivityPercent.equals("") == false) {
                startActivityPercent = " --pct-appswitch " + startActivityPercent;
            } else {
                startActivityPercent = "";
            }
            if (seedNum.equals("") == false) {
                seedNum = " -s " + seedNum;
            } else {
                seedNum = "";
            }
            if (delayTime.equals("") == false) {
                delayTime = " --throttle " + delayTime;
            } else {
                delayTime = "";
            }
            if (times.equals("") == false) {
                times = " " + times;
                String command = "monkey -p " + button_package.getText() + delayTime + swipePercent + systemClickPercent + startActivityPercent + clickPrcent + seedNum + times;
                Log.i("monkeyarg", "======" + command);
                ShellUtils.execCommand(command, true);


            } else {
                Looper.prepare();
                Toast toast = Toast.makeText(getApplicationContext(), "请输入monkey事件次数", Toast.LENGTH_SHORT);
                toast.show();
                Looper.loop();
            }
        }
    }



}
2.MainActivity布局如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/button_package"
        android:gravity="center"
        android:text="选择应用"
        android:background="@drawable/textview_border"
        />


    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/ed_1"
        android:inputType="number"

        android:hint="输入monkey滑动事件比例"/>


    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/ed_2"
        android:inputType="number"

        android:hint="输入monkey点击事件比例"/>


    <EditText
        android:layout_width="match_parent"
        android:id="@+id/ed_3"
        android:layout_height="wrap_content"
        android:inputType="number"

        android:hint="输入monkey系统按钮事件比例"/>


    <EditText
        android:layout_width="match_parent"
        android:id="@+id/ed_4"
        android:layout_height="wrap_content"
        android:inputType="number"

        android:hint="输入monkey的activity启动比例"/>



    <EditText
        android:layout_width="match_parent"
        android:id="@+id/ed_5"
        android:layout_height="wrap_content"
        android:inputType="number"

        android:hint="输入monkey随机种子数"/>


    <EditText
        android:layout_width="match_parent"
        android:id="@+id/ed_6"
        android:layout_height="wrap_content"
        android:inputType="number"

        android:hint="输入monkey延时时间"/>


    <EditText
        android:layout_width="match_parent"
        android:id="@+id/ed_7"
        android:layout_height="wrap_content"
        android:inputType="number"

        android:hint="输入monkey的事件数(必填)"/>
     <Button
        android:text="启动monkey"

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button" />

    <Button
        android:text="说明"

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button1" />
</LinearLayout>
3.在drawable下添加一个样式文件textview_border.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#ffffff" />
    <stroke android:width="1dip" android:color="#4fa5d5"/>
</shape>
4.shell命令执行工具类如下
package com.example.administrator.monkeyshareblog;

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;
        }
    }
}
5.新建一个activity,命名为PackageManageActivity ,代码如下
package com.example.administrator.monkeyshareblog;

import android.content.Intent;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;
//包名选择activity
public class PackageManageActivity extends AppCompatActivity {

    private ListView lv_app_list;
    private AppAdapter mAppAdapter;
    public Handler mHandler = new Handler();
    List<MyAppInfo> appInfos=new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();
        setContentView(R.layout.activity_package_manage);
        lv_app_list = (ListView) findViewById(R.id.lv_app_list);
        mAppAdapter = new AppAdapter();
        lv_app_list.setAdapter(mAppAdapter);
        initAppList();

        //点击listView条目跳转回主界面,并传包名到主应用
        lv_app_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                MyAppInfo myAppInfo=appInfos.get(position);
                Log.i("pacagename",myAppInfo.getAppName());
                Intent intent=new Intent(PackageManageActivity.this,MainActivity.class);
                intent.putExtra("packagename",myAppInfo.getAppName());
                Log.i("packagew1",myAppInfo.getAppName());
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);

            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    //获取app包名list并初始化界面
    private void initAppList(){
        new Thread(){
            @Override
            public void run() {
                super.run();
                //扫描得到APP列表
                appInfos = ApkTool.scanLocalInstallAppList(PackageManageActivity.this.getPackageManager());
                Log.i("pacagename11",appInfos.get(1).getAppName().toString());
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mAppAdapter.setData(appInfos);
                    }
                });
            }
        }.start();
    }



    class AppAdapter extends BaseAdapter {

        List<MyAppInfo> myAppInfos = new ArrayList<>();

        public void setData(List<MyAppInfo> myAppInfos) {
            this.myAppInfos = myAppInfos;
            notifyDataSetChanged();
        }

        public List<MyAppInfo> getData() {
            return myAppInfos;
        }

        @Override
        public int getCount() {
            if (myAppInfos != null && myAppInfos.size() > 0) {
                return myAppInfos.size();
            }
            return 0;
        }

        @Override
        public Object getItem(int position) {
            if (myAppInfos != null && myAppInfos.size() > 0) {
                return myAppInfos.get(position);
            }
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        
        //listview绑定数据
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder mViewHolder;
            MyAppInfo myAppInfo = myAppInfos.get(position);
            if (convertView == null) {
                mViewHolder = new ViewHolder();
                convertView = LayoutInflater.from(getBaseContext()).inflate(R.layout.package_item, null);
                mViewHolder.iv_app_icon = (ImageView) convertView.findViewById(R.id.iv_app_icon);
                mViewHolder.tx_app_name = (TextView) convertView.findViewById(R.id.tv_app_name);
                convertView.setTag(mViewHolder);
            } else {
                mViewHolder = (ViewHolder) convertView.getTag();
            }
            mViewHolder.iv_app_icon.setImageDrawable(myAppInfo.getImage());
            mViewHolder.tx_app_name.setText(myAppInfo.getAppName());
            return convertView;
        }

        class ViewHolder {

            ImageView iv_app_icon;
            TextView tx_app_name;
        }
    }



}
6.PackageManageActivity的布局代码如下
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:id="@+id/activity_package_manage"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/lv_app_list"
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:layout_height="match_parent"></ListView>
</LinearLayout>
7.新添一个listView条目布局文件package_item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:layout_height="60dp">

        <ImageView
            android:id="@+id/iv_app_icon"
            android:layout_weight="4"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <TextView
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:id="@+id/tv_app_name"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

</LinearLayout>






猜你喜欢

转载自blog.csdn.net/qq_31242531/article/details/80498476
今日推荐