adb常用命令(golang版)及输入中文
package main import (
"crypto/md5"
"fmt"
"image/png"
"io/ioutil" "log"
"os"
"regexp"
"strings" "bytes"
"os/exec"
"strconv"
"time"
) const (
//可用下面的AdbShellDumpsysActivityF函数获取包名和activity名
APPPackageName = "cn.XXX.android"
APP = "cn.XXX.android/com.XXX.XXXActivity"
) func main() { //如果手机是休眠状态,则打开电源
if AdbShellDumpsysPowerOff() {
AdbShellInputKeyEvent("") //power
}
//进入手机主屏
AdbShellInputKeyEvent("") //back
AdbShellInputKeyEvent("") //home
/*如果APP未启动,则启动APP
if !strings.Contains(AdbShellDumpsysActivityF(), APPPackageName) {
AdbShellAmStartN(APP)
}
*/
Tap("设置", )
TimeSleepDuration()
TapOnce(`\d我的`, , , )
AdbShellInputKeyEvent("") //power } //模拟按键,如按下home键,键值参考;https://blog.csdn.net/shililang/article/details/14449527
//adb shell input keyevent 3
func AdbShellInputKeyEvent(s string) {
exec.Command("adb", "shell", "input", "keyevent", s).Run()
} //模拟屏幕点击
//有的控件死活抓不到,只能直接点击
//adb shell input tap 900 800
func AdbShellInputTap(x, y int) {
x2 := strconv.Itoa(x)
y2 := strconv.Itoa(y)
exec.Command("adb", "shell", "input", "tap", x2, y2).Run()
} //模拟滑动
//adb shell input swipe 0 0 600 600
func AdbShellInputSwipe(x1, y1, x2, y2 int) {
xx1 := strconv.Itoa(x1)
yy1 := strconv.Itoa(y1)
xx2 := strconv.Itoa(x2)
yy2 := strconv.Itoa(y2)
exec.Command("adb", "shell", "input", "swipe", xx1, yy1, xx2, yy2).Run()
} //模拟长按 最后一个参数1000表示1秒,可将下面某个参数由500改为501,即允许坐标点有很小的变化。
//adb shell input swipe 500 500 500 500 1000
func AdbShellInputSwipeL(x1, y1, x2, y2, t int) {
xx1 := strconv.Itoa(x1)
yy1 := strconv.Itoa(y1)
xx2 := strconv.Itoa(x2)
yy2 := strconv.Itoa(y2)
exec.Command("adb", "shell", "swipe", "tap", xx1, yy1, xx2, yy2).Run()
} //模拟输入“字符”
//adb shell input text "abc"
//若需输入中文,可参考:https://blog.csdn.net/slimboy123/article/details/54140029
func AdbShellInputText(s string) {
exec.Command("adb", "shell", "input", "text", s).Run()
} //等待几秒
func TimeSleepDuration(x int) {
time.Sleep(time.Duration(x) * time.Second)
} //截屏并保存到当前目录下。
//由于需在手机和电脑上复制文件,必要时可增加延时或用下面的PathExists()判断文件是否存在,如:
//time.Sleep(time.Duration(2) * time.Second)
func AdbShellScreencapPullRm() {
exec.Command("adb", "shell", "screencap", "-p", "/sdcard/screen.png").Run()
exec.Command("adb", "pull", "/sdcard/screen.png", ".").Run()
exec.Command("adb", "shell", "rm", "/sdcard/screen.png").Run()
} //根据图像中某一片矩形区域的左上点和右下点,计算该部分图像点的MD5,以便比较图像
//后来发现不必用这种原始的办法,可以用下面的AdbShellUiautomatorDump()下载手机页面可视控件的XML文件进行解析
func ReadPngPart2MD5(x1, y1, x2, y2 int) string {
//先截图
AdbShellScreencapPullRm()
file, _ := os.Open("screen.png")
defer file.Close()
im, _ := png.Decode(file)
//x := im.Bounds().Max.X
//y := im.Bounds().Max.Y
//按行扫描
mybuff := new(bytes.Buffer)
for j := y1; j <= y2; j++ {
for i := x1; i <= x2; i++ {
r, g, b, a := im.At(i, j).RGBA()
mybuff.Write([]byte(fmt.Sprintf("%d ", r)))
mybuff.Write([]byte(fmt.Sprintf("%d ", g)))
mybuff.Write([]byte(fmt.Sprintf("%d ", b)))
mybuff.Write([]byte(fmt.Sprintf("%d ", a)))
}
}
ss := fmt.Sprint(md5.Sum(mybuff.Bytes()))
//fmt.Printf("MobileMainPage[%d,%d][%d,%d]sum:\n%s", x1, y1, x2, y2, ss)
return ss
} //判断设备是否休眠。重要补充:注意:这里有错误,需要将exec.Command中的命令用逗号分隔,不能直接findstr,应在代码中查找
//adb shell dumpsys power | findstr "Display Power:state="
func AdbShellDumpsysPowerOff() bool {
flag := false
MyCmd := exec.Command("cmd.exe /c adb shell dumpsys power | findstr \"Display Power:state=\"")
MyOut, _ := MyCmd.StdoutPipe()
MyCmd.Start()
MyBytes, _ := ioutil.ReadAll(MyOut)
MyCmd.Wait()
MyOut.Close()
s := string(MyBytes)
if strings.Contains(s, "Display Power: state=OFF") {
flag = true
}
return flag
} //查看手机上应用的packageName
//adb shell pm list packages
func AdbShellPmListPackages() string {
MyCmd := exec.Command("adb", "shell", "pm", "list", "packages")
MyOut, _ := MyCmd.StdoutPipe()
MyCmd.Start()
MyBytes, _ := ioutil.ReadAll(MyOut)
MyCmd.Wait()
MyOut.Close()
s := string(MyBytes)
return s
} //通过adb 查看最上层activity名字:
//adb shell dumpsys activity | findstr "mFocusedActivity"
//代码中不能直接执行findstr过滤,改正则匹配
func AdbShellDumpsysActivityF() string {
MyCmd := exec.Command("cmd.exe", "/c", "adb", "shell", "dumpsys", "activity")
MyOut, _ := MyCmd.StdoutPipe()
MyCmd.Start()
MyBytes, _ := ioutil.ReadAll(MyOut)
MyCmd.Wait()
MyOut.Close()
s := string(MyBytes)
//正则匹配mFocusedActivity
r := regexp.MustCompile(`mFocusedActivity.+?\}`)
match := r.FindString(s)
fmt.Println(match)
return match
} //启动activity,如计算器com.android.calculator2/com.android.calculator2.Calculator
//adb shell am start -n 包名/包名+类名(-n 类名,-a action,-d date,-m MIME-TYPE,-c category,-e 扩展数据,等
//如:adb shell am start -n com.android.camera/.Camera
func AdbShellAmStartN(p string) {
exec.Command("adb", "shell", "am", "start", "-n", p).Run()
} //获取当前应用屏幕上所有控件的信息并保存在sdcard下window_dump.xml文件里面. sdk版本16以上
//如:adb shell uiautomator dump --compressed /sdcard/window_dump.xml
//adb pull /sdcard/window_dump.xml .
//adb shell rm /sdcard/window_dump.xml
//可参考:https://blog.csdn.net/henni_719/article/details/72953251
//由于需在手机和电脑上复制文件,必要时可增加延时或用下面的PathExists()判断文件是否存在,如:
//time.Sleep(time.Duration(2) * time.Second) 但是经实测无需延时等待。
//特别提醒注意:对于可scroll的页面,只能dump出显示在屏幕上的可见的部分。即滑动页面后需重新dump。这个问题曾困扰我一天。
func AdbShellUiautomatorDump() {
//删除当前目录下的window_dump.xml
exec.Command("cmd", "/c", "del", "-y", "window_dump.xml").Run()
//重新dump
exec.Command("adb", "shell", "uiautomator", "dump", "/sdcard/window_dump.xml").Run()
exec.Command("adb", "pull", "/sdcard/window_dump.xml", ".").Run()
exec.Command("adb", "shell", "rm", "/sdcard/window_dump.xml").Run()
} //用正则找xml文件中bounds的坐标点
//感觉用xml解析不如用正则查找直观,这里需要你自己写正则表达式,返回bounds的两个坐标点[x1,y1][x2,y2]
//如:x1, y1, x2, y2 :=RegXmlPoint(`<node\s+index=\"\d+\"\s+text=\"我的\".+?\[(\d+),(\d+)\]\[(\d+),(\d+)\]`)
func RegXmlPoint(s string) (x1, y1, x2, y2 int) {
r := regexp.MustCompile(s)
file, _ := os.Open("window_dump.xml")
defer file.Close()
doc, _ := ioutil.ReadAll(file)
doc1 := string(doc)
match := r.FindStringSubmatch(doc1)
x1, _ = strconv.Atoi(match[])
y1, _ = strconv.Atoi(match[])
x2, _ = strconv.Atoi(match[])
y2, _ = strconv.Atoi(match[])
return x1, y1, x2, y2
} //用法如:Tap(`设置`,0) 将打开手机设置
//用正则根据`关键词`(反引号,可包含正则)匹配xml文件中node区域,其中有bounds的坐标点,计算bounds中心点,并Tap之
//第一个参数为匹配用的关键词,第二个参数ix表示点击匹配到的第几个,0表示第一个,-1表示最后一个
//正则参考:ss := fmt.Sprintf("%s%s%s", `<node.[^>]+?`, s, `.[^>]+?\[(\d+),(\d+)\]\[(\d+),(\d+)\].+?[^>]`)
// golang正则匹配任意汉字可用reg = regexp.MustCompile(`[\p{Han}]+`) 这里写正则费了较大功夫。
func Tap(s string, ix int) {
//先执行AdbShellUiautomatorDump函数。
AdbShellUiautomatorDump()
file, _ := os.Open("window_dump.xml")
defer file.Close()
doc, _ := ioutil.ReadAll(file)
doc1 := string(doc)
ss := fmt.Sprintf("%s%s%s", `<node.[^>]+?`, s, `.[^>]+?\[(\d+),(\d+)\]\[(\d+),(\d+)\].+?>`)
r := regexp.MustCompile(ss)
match := r.FindAllStringSubmatch(doc1, -)
le := len(match)
//匹配到1个或多个,ixx表示匹配到的第几个
ixx := ix
if le == {
log.Println("未匹配到:", s)
return
}
if ix < {
ixx = le + ix
}
if ixx < {
ixx =
} x1, _ := strconv.Atoi(fmt.Sprint(match[ixx][]))
y1, _ := strconv.Atoi(fmt.Sprint(match[ixx][]))
x2, _ := strconv.Atoi(fmt.Sprint(match[ixx][]))
y2, _ := strconv.Atoi(fmt.Sprint(match[ixx][])) xx := (x2-x1)/ + x1
yy := (y2-y1)/ + y1
log.Println(s)
AdbShellInputTap(xx, yy)
} //用法如:TapOnce(`我的`,0,10,105) 可改为递归调用自身
///意思是:点击含有`我的`关键词(反引号,可包含正则)的第一个node(0表示第1个);会打开新页面,10秒后返回后,再
//向上滑动页面,使该node的y2位置向上滚动到105px(页面上可滚动部分最上端的y1值,也就是上面不可滚动部分的y2值),使该node不可见。不能再点击。
//注意:此代码不通用,主要是向上滚动时从开始点[500,y2]滚动到结束点[500,pos],这里的开始和结束点要根据实际选择。
func TapOnce(s string, ix, tm, pos int) {
//先执行AdbShellUiautomatorDump函数。
AdbShellUiautomatorDump()
file, _ := os.Open("window_dump.xml")
defer file.Close()
doc, _ := ioutil.ReadAll(file)
doc1 := string(doc)
ss := fmt.Sprintf("%s%s%s", `<node.[^>]+?`, s, `.[^>]+?\[(\d+),(\d+)\]\[(\d+),(\d+)\].+?>`)
r := regexp.MustCompile(ss)
match := r.FindAllStringSubmatch(doc1, -)
le := len(match)
//匹配到1个或多个,ixx表示匹配到的第几个
ixx := ix
if le == {
log.Println("未匹配到:", s)
return
}
if ix < {
ixx = le + ix
}
if ixx < {
ixx =
} x1, _ := strconv.Atoi(fmt.Sprint(match[ixx][]))
y1, _ := strconv.Atoi(fmt.Sprint(match[ixx][]))
x2, _ := strconv.Atoi(fmt.Sprint(match[ixx][]))
y2, _ := strconv.Atoi(fmt.Sprint(match[ixx][])) xx := (x2-x1)/ + x1
yy := (y2-y1)/ + y1
log.Println(s)
AdbShellInputTap(xx, yy)
//此时app打开了新的内容页
TimeSleepDuration(tm)
AdbShellInputKeyEvent("") //back
TimeSleepDuration()
//向上滚动
AdbShellInputSwipe(, y2, , pos) } //判断文件或文件夹是否存在
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
} //未实现
func notimp(s ...string) {
/*
MyCmd := exec.Command("adb", "devices")
MyOut, _ := MyCmd.StdoutPipe()
MyCmd.Start()
MyBytes, _ := ioutil.ReadAll(MyOut)
MyCmd.Wait()
MyOut.Close()
fmt.Println(s)
return string(MyBytes)
*/
}
补充一:
输入中文:(参考:https://blog.csdn.net/slimboy123/article/details/54140029)
https://github.com/senzhk/ADBKeyBoard
第一步:从上面的地址下载安装ADBKeyBoard.apk文件
打开手机或模拟器,adb install ADBKeyBoard.apk安装该输入法
或者直接安装即可
第二步:设置默认输入法
在手机上找:设置-通用-语言和输入法 -默认-选择键盘-ADB Keyboard 然后确定,默认输入法也选择ADB keyboard(好像模拟器选择默认输入法的时候,hardware physical keyboard得off,默认是on)
第三步:用adb命令输入中文测试OK
adb shell am broadcast -a ADB_INPUT_TEXT --es msg '不错,可以学着品红酒的好工具'
然而,我这里还是乱码。用chcp 65001 改cmd字体为lucida console 也不行。而且产生了副作用,用chcp 936改不回来了(后面讲重置cmd)。
最后-------------------------------
参考:https://blog.csdn.net/u011068616/article/details/47945927 下面的mmc0531的评论
输入:adb shell am broadcast -a ADB_INPUT_B64 --es msg "5aSn5rGf" 成功了。(还有评论说不能输入半角空格,但可输入全角空格)
重置cmd,恢复初始状态:
用regedit.exe
HKEY_CURRENT_USER \ Console \ %SystemRoot%_system32_cmd.exe
删除文件夹 %SystemRoot%_system32_cmd.exe 就好了
(右键这个文件夹 有删除选项)
然后重启cmd 就恢复了默认设置
补充二:
adb 直接读取屏幕数据,速度更快 ,用 adb shell screencap -p
之前一直没搞定替换/r/n并保存为png
后来参考:https://studygolang.com/topics/4527/comment/13217
看了https://github.com/henson/Answer 的代码,原来是这样:
//GetImage 直接读取adb截图数据,速度更快
func (android *Android) GetImage() (img image.Image, err error) {
cmd := exec.Command("adb", "shell", "screencap", "-p")
var out bytes.Buffer
cmd.Stdout = &out if err = cmd.Run(); err != nil {
fmt.Println(err.Error())
return nil, err
}
x := bytes.Replace(out.Bytes(), []byte("\r\r\n"), []byte("\n"), -)
img, err = png.Decode(bytes.NewReader(x))
return
}
adb常用命令(golang版)及输入中文的更多相关文章
- ADB常用命令简洁版整理
ADB全称Android Debug Bridge ,“安卓调试桥梁”连接Android和电脑通信的桥梁. 市面上常见的手机助手,底层调研的都是ADB命令行. C/S架构命令行工具,客户端和服务端都 ...
- adb常用命令(转)
1.Android Debug Bridge -adb常用命令 1.1简介 Android Debug Bridge,我们一般简称为adb,主要存放在sdk安装目录下的platform-tools文件 ...
- adb常用命令教程
1.Android Debug Bridge - adb常用命令 1.1简介 Android Debug Bridge,我们一般简称为adb,主要存放在sdk安装目录下的platform-tools文 ...
- Android开发系列之adb常用命令
对于Android开发者来说,如果没有adb的帮助,那肯定就跟少了一只手那样别扭.其实笔者在刚刚学习Android开发的时候,也没有意识到adb的重要性.想想只要用IDE画出界面,然后实现后台的逻辑代 ...
- ADB常用命令(一)
转自:https://blog.csdn.net/qq_26552691/article/details/81348222 一.操作前请确认电脑上已配置好ADB环境.可在CMD命令行输入adb,如果出 ...
- adb常用命令-android学习第一天
转载出处:http://www.cnblogs.com/xiaoxuetu/ 转载来源:https://www.cnblogs.com/xiaoxuetu/p/3411214.html 平时开发and ...
- adb常用命令食用方法
一.什么是adb? adb是Android Debug Bridge的缩写,即安卓调试桥:那什么是安卓调试桥?简单来说,就是一个通用命令行工具,允许计算机与模拟器或连接的安卓设备之间进行通信,提供各种 ...
- adb 常用命令大全(1)- 汇总
adb 常用命令大全系列 基础命令 查看手机设备信息 应用管理 日志相关 模拟按键输入 其他实用功能
- 54. Android中adb常用命令及应用常用目录
本文主要介绍adb常用命令及应用常用目录.1.adb常用命令adb devices列出所有连接的android设备.以下命令都是对单个devices而言,如果存在多个devices的话,下面的命令都需 ...
随机推荐
- 按行切割大文件(linux split 命令简版)
按行切割大文件(linux split 命令简版) #-*- coding:utf-8 -*- __author__ = 'KnowLifeDeath' ''' Linux上Split命令可以方便对大 ...
- dnSpy 强大的.Net反编译软件
作者:D.泡沫 一说起.net的反编译软件,大家首先想到的就是Reflector,ILSpy,dotPeek等等.而dnSpy同样是一款优秀的反编译软件,同时它是开源免费的.官方的描述是: dnSpy ...
- 隔离 docker 容器中的用户
笔者在前文<理解 docker 容器中的 uid 和 gid>介绍了 docker 容器中的用户与宿主机上用户的关系,得出的结论是:docker 默认没有隔离宿主机用户和容器中的用户.如果 ...
- 痞子衡嵌入式:第一本Git命令教程(7.1)- 清理之缓存(stash)
今天是Git系列课程第七课,上一课我们学会了查看Git本地历史提交,今天痞子衡要讲的是Git仓库的清理操作,一共4个命令,都是日常开发中非常实用的命令,掌握这4个命令,会让你有一种玩弄Git仓库于股掌 ...
- SpringBoot基础系列-SpringBoot配置
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9990680.html SpringBoot基础系列-SpringBoot配置 概述 属性 ...
- 大前端的自动化工厂(1)——Yeoman
一.Yeoman是什么 Yeoman是现代化前端项目的脚手架工具,用于生成包含指定框架结构的工程化目录结构.它是整个前端自动化工厂的第一站. 从个人使用者的角度来看,Yeoman的地位有些鸡肋,因为流 ...
- [Linux] 大数据库导出大文件统计并去重
1. 把数据库表导出到文本文件中 mysql -h主机 -P端口 -u用户 -p密码 -A 数据库 -e "select email,domain,time from ent_login_0 ...
- 程序员奇谈之我写的程序不可能有bug篇
程序员在普通人的印象里是一份严(ku)谨(bi)的职业,也是一个被搞怪吐槽乐此不疲的职业,程序员们面对复杂的代码敲打电脑时连眉头都不会皱一下,但是有一个词却是他们痛苦的根源,它就是Bug. 有不少的新 ...
- OPC协议解析-关于OPC协议的几个问题
1 什么是OPC协议? 为了便于自动化行业不同厂家的设备和应用程序能相互交换数据,定义了一个统一的接口函数,就是OPC协议规范.有了OPC就可以使用统一的方式去访问不同设备厂商的产品数据. OP ...
- Xamarin 学习笔记 - 配置环境(Windows & iOS)
本文翻译自CodeProject文章:https://www.codeproject.com/Articles/1223980/Xamarin-Notes-Set-up-the-environment ...