用shell脚本模拟用户按键、触摸操作

Shell编程基础篇-上 1.1 前言 1.1.1 为什么学Shell Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具, Linux/UNIX系统的底层及基础应用软件的核心大都涉及Shell脚本的内容。每一个合格 的Linux系统管理员或运维工程师,都需要能够熟练地编写Shell脚本语言,并能够阅 读系统及各类软件附带的Shell脚本内容。只有这样才能提升运维人员的工作效率,... 阅读详情

之前写过两篇关于Android中模拟用户操作的博客(其实用一篇是转载的),现在就来讲讲用shell脚本来模拟用户按键操作。本次的目标是用shell脚本打开微信并在其搜索框中搜索相关内容。

 

  本文的模拟功能主要是用adb的input命令来实现,如果你adb的环境变量配置正确的话,在cmd中输入 adb shell input 就可以看见input的用法了。

usage: input ...
input text //输入文字(中文不支持)
input keyevent //keyevent按键
input [touchscreen|touchpad|touchnavigation] tap <x> <y>//点击屏幕
input [touchscreen|touchpad|touchnavigation] swipe <x1> <y1> <x2> <y2> //屏幕滑动 
input trackball press //滚球已经不用了
input trackball roll //滚球已经不用了
input rotationevent 0 1->90 2->180 3->270> //顺时针旋转
下面直接上安卓用户操作的代码,就一个MainActivity而已,UI、Mainfest都不用配置(可能需要root权限)</span>
package com.lsj.adb;

import java.io.DataOutputStream;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;

public class MainActivity extends Activity {

    private String[] search = {
            "input keyevent 3",// 返回到主界面,数值与按键的对应关系可查阅KeyEvent
            "sleep 1",// 等待1秒
            "am start -n com.tencent.mm/com.tencent.mm.ui.LauncherUI",// 打开微信的启动界面,am命令的用法可自行百度、Google
            "sleep 3",// 等待3秒
            "am start -n com.tencent.mm/com.tencent.mm.plugin.search.ui.SearchUI",// 打开微信的搜索
            "input text 123",// 像搜索框中输入123,但是input不支持中文,蛋疼,而且这边没做输入法处理,默认会自动弹出输入法
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //如果input text中有中文,可以将中文转成unicode进行input,没有测试,只是觉得这个思路是可行的
        search[5] = chineseToUnicode(search[5]);
        execShell(search);
    }

    /**
     * 执行Shell命令
     * 
     * @param commands
     *            要执行的命令数组
     */
    public void execShell(String[] commands) {
        // 获取Runtime对象
        Runtime runtime = Runtime.getRuntime();

        DataOutputStream os = null;
        try {
            // 获取root权限,这里大量申请root权限会导致应用卡死,可以把Runtime和Process放在Application中初始化
            Process process = runtime.exec("su");
            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("\n");
                os.flush();
            }
            os.writeBytes("exit\n");
            os.flush();
            process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 把中文转成Unicode码
     * @param str
     * @return
     */
    public String chineseToUnicode(String str){
        String result="";
        for (int i = 0; i < str.length(); i++){
            int chr1 = (char) str.charAt(i);
            if(chr1>=19968&&chr1<=171941){//汉字范围 \u4e00-\u9fa5 (中文)
                result+="\\u" + Integer.toHexString(chr1);
            }else{
                result+=str.charAt(i);
            }
        }
        return result;
    }

    /**
     * 判断是否为中文字符
     * @param c
     * @return
     */
    public  boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
            return true;
        }
        return false;
    }


}

模拟用户打开微信,并进行搜索就这么完成了。其实这里用shell命令模拟用户操作还是有些问题的,比如说控件长按(sendevent),好难理解,而且需要跟其中传递的控件坐标参数应该要跟屏幕分辨率联系起来,实际应用范围不是很广泛。PS:那种大量需要重复操作的除外,如:自动化测试,游戏刷图(PS:腾讯的仙剑手游把我大仙剑毁了啊,麻花腾你妹啊,你全家都是麻花腾)。

  最后,其实可以参考下按键精灵,这款应用做的还不错,除了不给root权限就崩外....

 

补充:以上模拟用户操作的代码在交互不频繁的情况下是完全没有问题的,但是如果使用频繁的话,会发生多次申请root权限,导致系统卡死的现象,后面在google上找到了一个开源项目,可以解决这个问题(它使用的是单例模式),代码如下:

/**
 * 类名 RootContext.java 说明 获取root权限 创建日期 2012-8-21 作者 LiWenLong Email
 * lendylongli@gmail.com 更新时间 $Date$ 最后更新者 $Author$
 */
public class RootContext {
    private static RootContext instance = null;
    private static Object mLock = new Object();
    String mShell;
    OutputStream o;
    Process p;

    private RootContext(String cmd) throws Exception {
        this.mShell = cmd;
        init();
    }

    public static RootContext getInstance() {
        if (instance != null) {
            return instance;
        }
        synchronized (mLock) {
            try {
                instance = new RootContext("su");
            } catch (Exception e) {
                while (true)
                    try {
                        instance = new RootContext("/system/xbin/su");
                    } catch (Exception e2) {
                        try {
                            instance = new RootContext("/system/bin/su");
                        } catch (Exception e3) {
                            e3.printStackTrace();
                        }
                    }
            }
            return instance;
        }
    }

    private void init() throws Exception {
        if ((this.p != null) && (this.o != null)) {
            this.o.flush();
            this.o.close();
            this.p.destroy();
        }
        this.p = Runtime.getRuntime().exec(this.mShell);
        this.o = this.p.getOutputStream();
        system("LD_LIBRARY_PATH=/vendor/lib:/system/lib ");
    }

    private void system(String cmd) {
        try {
            this.o.write((cmd + "\n").getBytes("ASCII"));
            return;
        } catch (Exception e) {
            while (true)
                try {
                    init();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
        }
    }

    public void runCommand(String cmd) {
        system(cmd);
    }

    /**
     * 判断是否已经root了
     * */
    public static boolean hasRootAccess(Context ctx) {
        final StringBuilder res = new StringBuilder();
        try {
            if (runCommandAsRoot(ctx, "exit 0", res) == 0)
                return true;
        } catch (Exception e) {
        }
        return false;
    }

    /**
     * 以root的权限运行命令
     * */
    public static int runCommandAsRoot(Context ctx, String script,
            StringBuilder res) {
        final File file = new File(ctx.getCacheDir(), "secopt.sh");
        final ScriptRunner runner = new ScriptRunner(file, script, res);
        runner.start();
        try {
            runner.join(40000);
            if (runner.isAlive()) {
                runner.interrupt();
                runner.join(150);
                runner.destroy();
                runner.join(50);
            }
        } catch (InterruptedException ex) {
        }
        return runner.exitcode;
    }

    private static final class ScriptRunner extends Thread {
        private final File file;
        private final String script;
        private final StringBuilder res;
        public int exitcode = -1;
        private Process exec;

        public ScriptRunner(File file, String script, StringBuilder res) {
            this.file = file;
            this.script = script;
            this.res = res;
        }

        @Override
        public void run() {
            try {
                file.createNewFile();
                final String abspath = file.getAbsolutePath();
                Runtime.getRuntime().exec("chmod 777 " + abspath).waitFor();
                final OutputStreamWriter out = new OutputStreamWriter(
                        new FileOutputStream(file));
                if (new File("/system/bin/sh").exists()) {
                    out.write("#!/system/bin/sh\n");
                }
                out.write(script);
                if (!script.endsWith("\n"))
                    out.write("\n");
                out.write("exit\n");
                out.flush();
                out.close();

                exec = Runtime.getRuntime().exec("su");
                DataOutputStream os = new DataOutputStream(
                        exec.getOutputStream());
                os.writeBytes(abspath);
                os.flush();
                os.close();

                InputStreamReader r = new InputStreamReader(
                        exec.getInputStream());
                final char buf[] = new char[1024];
                int read = 0;
                while ((read = r.read(buf)) != -1) {
                    if (res != null)
                        res.append(buf, 0, read);
                }

                r = new InputStreamReader(exec.getErrorStream());
                read = 0;
                while ((read = r.read(buf)) != -1) {
                    if (res != null)
                        res.append(buf, 0, read);
                }

                if (exec != null)
                    this.exitcode = exec.waitFor();
            } catch (InterruptedException ex) {
                if (res != null)
                    res.append("\nOperation timed-out");
            } catch (Exception ex) {
                if (res != null)
                    res.append("\n" + ex);
            } finally {
                destroy();
            }
        }

        public synchronized void destroy() {
            if (exec != null)
                exec.destroy();
            exec = null;
        }
    }
}

本文转载于:http://www.cnblogs.com/travellife/p/4108208.html

Shell分类详解(图形界面+命令行式) Shell的两大分类详解 阅读详情

相关推荐

Android开发——使用ADB Shell命令实现模拟点击(支付宝自动转账实现)

首先声明,本人反对一切利用技术的违法行为本文的实现代码已经销毁,本文以介绍流程为主1.这里所说的模拟点击不是在自己的APP里点击,点自己APP上的控件没什么好说的不仅是支付宝转账,其他的获取别人百度云里的某个文件信息,或者获取别人邮箱APP里的邮件等都是可以实现的。这里我们要实现的是,通过一定的触发条件,开启我们事先嵌入到应用代码里的脚本命令(其实就是Shell语句的代码实现),这个触发条件根...

weixin_30367945的博客 3795

shell的模拟实现

目录 整体框架分析 代码演示 代码分析

bit_zyx的博客 1776

Android自动化测试之Shell脚本

基础 1、Android中查看当前正在运行的进程以及am start启动方式 adb shell logcat |findstr "cmp=" 当出现的log暂停时,最后显示的就是当前的进程信息:包(package)名/包名.活动(activity)名称 启动进程:adb shell am start -n 包(package)名/包名.活动(activity)名称 cr:http://blog.sina.com.cn/s/blog_628cc2b70102veoa.html ...

chibrow的博客 837

【Linux】shell的简单模拟实现

shell模拟实现

m0_62179366的博客 2079

Android基于Socket无线遥控(2)--模拟触摸按键篇

按计划每周更新一篇技术博文,第五篇:《Android基于Socket无线遥控(2)--无线控制篇》   本篇主要内容涉及模拟系统按键消息,单击事件,触屏事件等,模拟Android系统按键参考了网上资料(见引用1),无线遥控收发信息部分和上节所讲内容一样。 一、技术介绍 1.模拟按键及触屏相关     模拟按键和触摸屏需要调用SDK内部隐藏方法,在WindowManagerS

钟秀 1万+

ADB 模拟触摸和按键

解锁adb shell input keyevent 82查看设备与与event的对应关系cat /proc/bus/input/devicesgetevent获取屏幕输入事件,通过input tap命令模拟触摸屏幕input tap 600 800模拟的是滑动事件input swipe input swipe 100 800 700 800

pan0755的博客 2982

Android随笔之——用shell脚本模拟用户按键、触摸操作

之前写过两篇关于Android中模拟用户操作的博客(其实用一篇是转载的),现在就来讲讲用shell脚本来模拟用户按键操作。本次的目标是用shell脚本打开微信并在其搜索框中搜索相关内容。     本文的模拟功能主要是用adb的input命令来实现,如果你adb的环境变量配置正确的话,在cmd中输入 adb shell input 就可以看见input的用法。 usage: i

gnnulzy的博客 1215

adb shell input使用,android模拟触屏、事件触发、拖拽等操作

shell控制端下使用input可以实现模拟触屏、虚拟按键及其他触摸操作,具体选项如下 一、 text <string> (Default: touchscreen) 向当前输入框中键入字符串,如input text "cs input text" 二、keyevent [–longpress] <key code number or name> … (Default: keyboard) 发送事件,测试发现,该动作无法实现长按动作,即使使用–longpr

qq_43547638的博客 8343

android 使用shell模拟触屏_Android随笔之——用shell脚本模拟用户按键、触摸操作...

之前写过两篇关于Android中模拟用户操作的博客(其实用一篇是转载的),现在就来讲讲用shell脚本来模拟用户按键操作。本次的目标是用shell脚本打开微信并在其搜索框中搜索相关内容。本文的模拟功能主要是用adb的input命令来实现,如果你adb的环境变量配置正确的话,在cmd中输入adb shell input就可以看见input的用法了。usage: input ...input te...

weixin_39963744的博客 916

伪距单点定位算法原理以及利用最小二乘法计算实例

即该公式:建立下列代价函数满足最佳估值的条件为:即:可解得未知参数 X 的最佳估值由于每个可见卫星观测量的精度可能不一样,这时,需要对不同观测量赋予一个权重系数,称为加权。

qq_43381998的博客 1万+

无刷电机FOC控制入门:磁场、洛伦兹力与坐标转换详解

本文深入解析无刷电机FOC(磁场定向控制)的核心原理,从电磁学基础的磁场与洛伦兹力出发,详细阐述了如何通过Clarke变换、Park变换等坐标转换技术,将三相交流解耦为直流量进行控制,最终利用SVPWM技术实现平滑、高效的电机驱动。文章旨在帮助开发者理解FOC的物理本质与数学框架,为机器人、无人机等高性能应用奠定基础。

weixin_29306011的博客 265

《Android基于Socket无线遥控(2)--无线控制篇》

按计划每周更新一篇技术博文,第五篇:《Android基于Socket无线遥控(2)--无线控制篇》   本篇主要内容涉及模拟系统按键消息,单击事件,触屏事件等,模拟Android系统按键参考了网上资料(见引用1),无线遥控收发信息部分和上节所讲内容一样。 一、技术介绍 1.模拟按键及触屏相关     模拟按键和触摸屏需要调用SDK内部隐藏方法,在WindowManagerS

pugongying1988的专栏 2571

PaddleOCR PP-OCRv5实战:5分钟搞定身份证信息提取(附完整代码)

本文详细介绍了如何利用PaddleOCR的PP-OCRv5模型,在5分钟内快速搭建身份证信息提取流程。文章从环境搭建、核心代码实战出发,深入解析了PP-OCRv5针对证件识别的优化特性,并提供了从OCR结果到结构化数据的完整处理方案与避坑指南,帮助开发者高效实现AI驱动的自动化信息提取。

salt9的博客 782

shell脚本实现简单的模拟用户操作,未加检查点。

计次失败:counter+1,输出的一直是times==0 shell脚本: echo about eyelock counter=0 am start --activity-single-top -n com.android.settings/com.android.settings.Settings while : do sleep 2 input keyevent KEYCODE_B

weiliangusb的专栏 746

计算机网络之NAT的解释与实验配置

NAT 静态NAT 动态NAT easy_ip NAT服务器映射

爱学习的JackYang的博客 1916

Keil v5.11给STM32烧录程序记录

1)安装KeilMDK511 2)安装ST Link下载器驱动 3)打开Keil v5,加载工程文件 4)load pack(Keil.STM32F1xx_DFP.1.1.0和Keil.STM32F0xx_DFP.1.2.0) 5)编译程序- 0 Error(s), 0 Warning(s). 6)烧录程序 ...

守望的距离 6281

adb shell 模拟按键,触摸事件

1 发送按键事件(KEY): 命令格式:adb shell sendevent [device] [type] [code] [value] 如:  adb shell sendevent /dev/input/event0 1 229 1 代表按下按下menu键 adb shell sendevent /dev/input/event0 1 229 0 代表按下松开m

小亮的专栏 1万+

[cadence]Allegro STEP-3D模型导入、匹配、导出的方法及注意事项

如果 Avaliable里面没有和symbols对应的文件,说明没有对应的3D模型,这时候需要在你的step路径下创建y与 .dra 封装文件相同名称的。选择好 Output file 和 name 之后呢,点击 Export。首先打开Setup - Step Package Mapping。注意:路径中不能有中文名称,有的话你会发现不能导出,也不会报错。在路径下将下载或者自己做的 3D模型文件改名之后,重新打开。可在View -> 3D View。

LuDvei的博客 2万+

android shell模式下模拟触摸屏点击和按键点击

adb shell命令模式下: input keyevent 3 // Home input keyevent 4 // Back input keyevent 19 //Up input keyevent 20 //Down input keyevent 21 //Left input keyevent 22 //Right input keyevent 23...

q1285067278的专栏 3348

[QMT和ptrade量化交易小白入门]-121、如何用K-means聚类,每月自动筛选高流动性ETF

本专栏主要是介绍QMT和ptrade的基础用法,常见函数,写策略的方法,也会分享一些量化交易的思路,大概会写200篇左右。QMT的相关资料较少,在使用过程中不断的摸索,遇到了一些问题,记录下来和大家一起沟通,共同进步。

木头大左的博客 827

【XAI】透视深度学习:CNN与Transformer的可解释性方法

深度学习模型的可解释性方法解析:本文探讨了CNN和Transformer两类主流模型的可解释性技术。针对CNN,介绍了显著性图、类激活图(CAM/Grad-CAM)和基于扰动的方法,通过可视化重要像素区域揭示决策依据。对于Transformer,重点分析了注意力机制可视化及其在文本处理中的应用,并介绍了积分梯度等归因方法。文章包含详细的Python实现示例(使用Captum库),涵盖从MNIST图像显著性分析到BERT文本注意力可视化,为初学者提供了可操作的技术指南。这些方法有助于增强模型透明度,提升AI系

u012133341的博客 381

解放双手!ADB模拟按键与触摸控制全攻略

你是否还在为重复的手机操作感到厌烦?想要自动化测试应用却不知从何入手?本文将带你掌握ADB(Android Debug Bridge,安卓调试桥)的设备控制技巧,通过简单命令实现按键模拟与触摸操作,让手机操作效率提升10倍!读完本文,你将学会如何用一行代码控制手机按键、模拟滑动解锁、输入文本,甚至实现简单的自动化操作。 ## ADB设备控制基础 ADB是连接电脑与Android设备的强大工具,...

gitblog_01169的博客 1306

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

android 使用shell模拟触屏_android命令行模拟输入事件(文字、按键、触摸等)

前言通过adb shell input可以模拟android各种输入事件,比如文字、按键、触摸等等。adb shell inputUsage: input [] [...]The sources are:keyboardmousejoysticktouchnavigationtouchpadtrackballdpadstylusgamepadtouchscreenThe commands and...

weixin_39841136的博客 1156

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

上一篇: Android下am和pm命令简介
下一篇: 【Android自动化打包】01. aapt的用法
和技术赛跑
博客等级 码龄11年 80粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值