appium移动自动化详解
1移动自动化简介
移动自动化就是通过代码来控制手机,模拟人的动作,对手机进行一些点击,输入等操作,那python代码如何能控制到手机呢?目前的思路应该是python代码->Appium-python库->Appium服务->手机。也就是通过appium的库来调用appium服务,让appium服务对手机进行操作。
基于上面的思路,我们环境安装好之后,运行代码之前,需要先将环境开起来,appium服务开启,安卓模拟器开启,就可以运行安卓自动化代码了。如果运行报错没有找到安卓设备的话,试试看在cmd里面输入adb connect 设备名,比如adb connect 127.0.0.1:62001
1.1连接手机的代码
写自动化代码之前,首先写一段下面的代码,用来连接上手机,并且连接上你需要测试的APP,如果报错没有找到设备的话,按照上面说的运行adb connect 设备名试试看。
# encoding=utf-8
from appium import webdriver server = r'http://localhost:4723/wd/hub' # Appium Server, 端口默认为4723
desired_capabilities = {
'platformName': 'Android', # 平台
# 需替换成你的driverName,如果不知 道自己的设备名,用adb命令去查看一下
'driverName': '127.0.0.1:62001',
'platformVersion': '5.1.1', # 安卓版本
'appPackage': 'com.android.settings', #APP包名
'appActivity': '.Settings' # APP启动名
'unicodeKeyboard': True # 这句和下面那句是避免中文问题的
'resetKeyboard': True
}
driver = webdriver.Remote(server, desired_capabilities) # 连接手机和APP
driver.find_element_by_id("com.android.settings:id/title").click() # 后面讲
driver.quit() # 退出driver
在上面的代码driver.quit()之前加入下面的代码,获取当前APP的包名和启动名
# 获取APP的包名
print(driver.current_package)
#获取APP的启动名
print(driver.current_activity)
打印的结果:
com.android.settings
.SubSettings
2 UIAutomatorViewer使用
在讲元素定位之前,首先说一个很有用的工具 UIAutomatorViewer,这个工具在\android-sdk-windows\tools文件夹下面,uiautomatorviewer.bat这个文件,双击打开。
第一步:打开之后看到的界面应该是:
(这里提示一下:如果打开的时候报错了,“Error obtaining UI hierarchy”错误,不能找到ui,一般就是因为adb被占用了,那么可以试着关闭adb,去cmd里面输入adb kill-server,再输入adb start-server,重启后等会再去点,如果还是不行,多等会,再不行就把appium的服务关掉)
(再提示:打开uiantomatorviewer的时候还会打开一个黑框,这个黑框别关)
第二步,打开你的虚拟器或者真机中的需要测试的APP,比如我现在测试设置,我就打开设置,如图:
第三步:点击第一步图示的圈红按钮,点击后等待一会,会出来如下图:
第四步,出来上图后,想要哪个按钮的id或者name,就用鼠标点到哪个按钮上,比如我想要看更多按钮的信息,点击“更多”,就在右面界面中出来了text,id,class等信息,其中的resourse-id就是id名。
第五步:这个工具还可以保存当前页面,这样方便以后多次查看当前页面的控件内容,而不用每次去打开APP,操作步骤,点击保存按钮,工具栏里面的第四个按钮,保存后,会同时保存两个文件,一个png文件,一个uix文件。保存后怎么打开呢?点击工具上的第一个按钮,open,点击后会弹出一个框,如图:
上面那个路径是刚才保存的png路径,下面是uix路径,原来保存的名字可能是dump开头的,改一下名字,png和uix可以改成一样的,这样再次打开的时候比较容易找。这样打开跟之前的方法打开出来的结果一样。
3 appium自动化测试代码编写
3.1定位元素
做自动化测试最重要的是要先定位到元素,appium定位元素和selenium类似,准确的说appium也是继承了selenium的方法。
3.1.1通过id定位元素
driver.find_element_by_id("com.android.settings:id/title")
这个方法的参数写的是id名,也就是resourse-id的值。这样就找到id为"com.android.settings:id/title"的控件了,可以对它进行click等操作。
3.1.2通过class定位元素
接着上面的代码:driver.find_element_by_id("com.android.settings:id/title").click(),再写一句:
driver.find_element_by_class_name("android.widget.ImageButton").click()
参数为“class”的值。
通过class name找到返回按钮,点击返回按钮。
3.1.3通过xpath定位元素
driver.find_element_by_xpath("//*[contains(@text, '更多')]").click()
driver.find_element_by_xpath("//*[contains(@content-desc, '向上')]").click()
全部的测试代码为:
# encoding=utf-8 from appium import webdriver
import time server = r'http://localhost:4723/wd/hub' # Appium Server, 端口默认为4723
desired_capabilities = {
'platformName': 'Android',
'driverName': '127.0.0.1:62001', # 需替换成你的driverName
'platformVersion': '5.1.1',
'appPackage': 'com.android.settings',
'appActivity': '.Settings'
}
driver = webdriver.Remote(server, desired_capabilities) # 连接手机和APP
driver.find_element_by_id("com.android.settings:id/title").click() # 点击wlan
#time.sleep(2)
driver.find_element_by_class_name("android.widget.ImageButton").click() # 点击返回
#time.sleep(2)
driver.find_element_by_xpath("//*[contains(@text, '更多')]").click() # 点击更多
#time.sleep(2)
driver.find_element_by_xpath("//*[contains(@content-desc, '向上')]").click() # 点击返回
#time.sleep(2)
driver.quit()
3.2定位多个元素
上面那些方法可以定位到一个元素,那么find_elements_by_XXX可以找到多个元素,然后通过下标找你需要的元素。
比如上面那段代码中的这句话:
driver.find_element_by_id("com.android.settings:id/title").click()
这里的id其实并不是唯一的,仔细看看设置页面的其他的元素id,id值也都是这些。
所以可以像下面这样写:
eles = driver.find_elements_by_id("com.android.settings:id/title")
print(type(eles))
eles[0].click() # 点击eles这个列表的第一个元素
eles的类型是list。
3.3 WebDriverWait显示等待
在一个超时时间范围内,每隔一段时间去搜索一次元素是否存在,一旦找到,就返回,没有找到就每隔一段时间找一次,直到超时后报错。
代码编写如下:
# 创建一个WebDriverWait类的对象,传三个参数,第一个参数为driver,第二个参数是总共查找的时间,单位秒,第三个参数为每隔1秒的时间查找一次,如果查找时间超过10秒还没找到,就报超时错误。
wdw = WebDriverWait(driver, 10, 1)
# wdw对象的方法有一个until()方法,这个方法的参数是一个匿名函数,这里的匿名函数,形参x传入的是driver,后面的表达式就是通过xpath找到更多这个按钮。
ele = wdw.until(lambda x:x.find_element_by_xpath("//*[contains(@text, '更多')]"))
ele.click()
使用前需要导入包:
from selenium.webdriver.support.ui import WebDriverWait
3.4元素操作
3.4.1点击元素
click() # 上面已经使用过
3.4.2发送数据到输入框
send_keys(value):
ele.send_keys(“test”)
3.4.3清空输入框的元素
clear():
ele.clear
代码示例:
# encoding=utf-8 from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import time server = r'http://localhost:4723/wd/hub' # Appium Server, 端口默认为4723
desired_capabilities = {
'platformName': 'Android',
'driverName': '127.0.0.1:62001', # 需替换成你的driverName
'platformVersion': '5.1.1',
'appPackage': 'com.android.settings',
'appActivity': '.Settings'
}
driver = webdriver.Remote(server, desired_capabilities)
wdw = WebDriverWait(driver, 10, 1)
# 点击搜索
serach = wdw.until(lambda x:x.find_element_by_xpath("//*[contains(@content-desc, '搜索')]"))
serach.click()
# 输入搜索内容
serach_text = wdw.until(lambda x : x.find_element_by_id("android:id/search_src_text"))
serach_text.send_keys("设置") # 清空搜索内容
serach_text.clear()
time.sleep(3) driver.quit()
3.4.4获取元素的文本内容
text:
wlan_button = driver.find_element_by_id("com.android.settings:id/title")
print(wlan_button.text)
3.4.5获取元素的属性值
get_attribute(“属性名称”):
value的值可以是name,text,className,resourceId
name:首先返回content-desc的值,如果没有content-desc,就返回text属性
text:返回text的属性值
className:返回class属性值,只有API在18版本以上才支持
resourceId:返回resource-id属性值,只有API在18版本以上才支持
wdw = WebDriverWait(driver, 10, 1)
serach = wdw.until(lambda x:x.find_element_by_xpath("//*[contains(@content-desc, '搜索')]"))
print("className:%s"%serach.get_attribute("className"))
print("resourceId:%s"%serach.get_attribute("resourceId"))
print("name:%s"%serach.get_attribute("content-desc")) # 上面那段写的是输入”name”,首先返回content-desc的值,但是现在新版本输入“name”就只返回text的值,所以如果输入name没有得到想要的,就试试看这样写get_attribute("content-desc")
print("name:%s"%serach.get_attribute("checked")) # 返回True或者Flase,还有别的属性也类似使用即可。
3.4.6获取元素的位置
location:
想要获取元素的位置,首先理解一下坐标点,APP的每个控件元素都有一个坐标点,比如下面的左上角的设置控件,左上角的坐标点是(24,59),右下角的坐标点是(84,100)。
越往右,x坐标点越大,越往下,y坐标点值越大。
wdw = WebDriverWait(driver, 10, 1)
serach = wdw.until(lambda x:x.find_element_by_xpath("//*[contains(@content-desc, '搜索')]"))
print(serach.location) # 返回一个字典:{'x': 648, 'y': 44}
3.4.7获取控件的class
tag_name:
driver.find_element_by_name(u"菜单").tag_name
3.4.8判断该控件是否对用户可见
is_displayed:
driver.find_element_by_id("xxx").is_displayed() 返回True或False
3.4.9获取控件的大小
size:
driver.find_element_by_id("xxx").size
3.5滑动和拖拽
3.5.1 swipe:从A点滑动至B点,滑动时间为毫秒
driver.swipe(279,1081,320,354)
前面两个值是A点的x,y坐标,后面两个值是B点的x,y坐标,上面那个意思就是从下面的某个点滑动到上面某个点,模拟手机从下往上滑,第五个参数也可以写,是个可选参数,意思是滑动总共花费的时间,单位是毫秒,有一个默认时间大约0.8s左右,比如:
driver.swipe(279,1081,320,354,5000)意思就是说从A点滑动到B点总共花费5s,可以和上面的比较一下,可以看出5s滑动的速度慢了,惯性小了。
还有一个类似的方法,按住A点后快速滑动至B点:
driver.flick(start_x, start_y, end_x, end_y):传入的也是AB点的坐标,
3.5.2 scroll滑动事件:从一个元素滑动到另一个元素
# 找到应用元素
ying_yong = driver.find_element_by_xpath("//*[contains(@text, '应用')]")
# 找到蓝牙元素
lan_ya = driver.find_element_by_xpath("//*[contains(@text, '蓝牙')]")
从应用元素滑动到蓝牙元素
driver.scroll(ying_yong, lan_ya)
3.5.3 drag 拖拽事件
ying_yong = driver.find_element_by_xpath("//*[contains(@text, '应用')]")
lan_ya = driver.find_element_by_xpath("//*[contains(@text, '蓝牙')]")
driver.drag_and_drop(ying_yong, lan_ya)
drag和scroll的区别:drag是没有惯性的,所谓没有惯性的意思是每次滑动,滑动停止的位置都是一样的,scroll从同一个元素滑动到另一个元素,多次运行的结果可能会不一样。swipe
方法的最后一个参数时间设置的长一些,效果会等同于drag,如果不设置时间,那效果就等同于scroll。
多次滑动,可以参考下面的代码,要注意的是,find_element_by_xxx这个方法只找显示在当前页面的元素,不会找没有显示在当前页面的元素。
ying_yong = driver.find_element_by_xpath("//*[contains(@text, '应用')]")
lan_ya = driver.find_element_by_xpath("//*[contains(@text, '蓝牙')]")
driver.drag_and_drop(ying_yong, lan_ya)
# 下面这个按钮不可以放到上面去,因为上句话是滑动,备份和重置按钮只有在滑动后才能看到
bei_fen = driver.find_element_by_xpath("//*[contains(@text, '备份')]") driver.drag_and_drop(bei_fen, ying_yong)
3.5.4综合应用1
如果页面上有”关于手机”元素,就点击,否则就向下翻页,直到找到”关于手机”元素,点击它,,再判断关于手机页面是否有“5.1.1”。
# encoding=utf-8
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import time server = r'http://localhost:4723/wd/hub' # Appium Server, 端口默认为4723
desired_capabilities = {
'platformName': 'Android',
'deviceName': '127.0.0.1:62001', # 需替换成你的deviceName
'platformVersion': '5.1.1',
'appPackage': 'com.android.settings',
'appActivity': '.Settings'
}
driver = webdriver.Remote(server, desired_capabilities) while True:
try:
about_button = driver.find_element_by_xpath("//*[contains(@text, '关于')]")
about_button.click()
time.sleep(2)
break
except Exception:
# 向下翻页
# 这里还要注意,翻完页之后,上一页的最下面的元素还应该在页面上,以免丢失元素
driver.swipe(320,1081,320,500,3000)
# 判断关于我们页面是否有5.1.1
eles = driver.find_elements_by_id("android:id/summary")
for i in eles:
# if "5.1" in i.text: # 判断只要包含5.1就可以
if i.text == "5.1.1": # 判断i.text必须等于5.1.1
print("有5.1.1")
break
else:
print("没有") driver.quit()
for...else...语法:for循环正常执行完毕的情况下(没有执行break语句),继续执行else语法,如果不是正常执行完毕的,即执行了break语言,就不执行else语句了。
3.6高级手势 TouchAction
TouchAction是AppiumDriver的辅助类,主要针对手势操作,比如滑动、长按、拖动等,原理是将一系列动作放在一个链条中发送到服务器,服务器接收到该链条后,解析各个动作,逐个执行。
3.6.1手指轻敲
模拟手机轻轻点击一下屏幕的操作方法为:
tap(element=None, x=None, y=None, count=1)
其中element是被定位到的元素,x,y是敲击的坐标点
然后使用perform()方法发送命令到服务器执行
from appium import webdriver from appium.webdriver.common.touch_action import TouchAction # 导包 server = r'http://localhost:4723/wd/hub' # Appium Server, 端口默认为4723 desired_capabilities = { 'platformName': 'Android', 'deviceName': '127.0.0.1:62001', # 需替换成你的deviceName 'platformVersion': '5.1.1', 'appPackage': 'com.android.settings', 'appActivity': '.Settings' } driver = webdriver.Remote(server, desired_capabilities) tc = TouchAction(driver) # 创建TouchAction类对象 # more_button = driver.find_element_by_xpath("//*[contains(@text, '更多')]") # tc.tap(more_button).perform() # 可以直接传入找到的元素 tc.tap(x=108, y=445).perform() # 也可以不找元素,直接传入坐标
3.6.2手指按下和抬起
# 前面的代码都一样
driver = webdriver.Remote(server, desired_capabilities)
more_button = driver.find_element_by_xpath("//*[contains(@text, '更多')]")
tc = TouchAction(driver)
tc.tap(more_button).perform()
# tc.press(x=24, y=478).perform() # 按下某个点,不松开
tc.press(x=24, y=478).wait(5000).release().perform() # 按下某个点,等待5秒钟后,松开。可以理解为长按
用到的方法:
press(element=None, x=None, y=None, count=1):长按
wait(time):等待多少毫秒
release():释放
3.6.3长按 long_press
方法:
TouchAction(driver).long_presss(el=None, x=None, y=None, duration=1000)
el意思是可以传入一个查找到的元素,
x,y意思是传入坐标点
duration,是长按的时间,单位毫秒,默认1s
driver = webdriver.Remote(server, desired_capabilities) tc = TouchAction(driver) driver.find_element_by_xpath("//*[contains(@text, 'WLAN')]").click() time.sleep(2) tc.long_press(driver.find_element_by_xpath("//*[contains(@text, 'SSID')]")).perform()
3.6.4移动move_to()方法
move_to(el=None, x=None, y=None):
这个方法跟前面的方法类似,第一个参数可以传入一个找到的元素,第二个和第三个元素可以传入坐标点,选择哪种方法都可以。
假如想要更改解锁图案为如图的样子:
代码可以如下:
# encoding=utf-8 from appium import webdriver from appium.webdriver.common.touch_action import TouchAction from selenium.webdriver.support.wait import WebDriverWait server = r'http://localhost:4723/wd/hub' # Appium Server, 端口默认为4723 desired_capabilities = { 'platformName': 'Android', 'deviceName': '127.0.0.1:62001', # 需替换成你的deviceName 'platformVersion': '5.1.1', 'appPackage': 'com.android.settings', 'appActivity':'.ChooseLockPattern' # 活动名,解锁图案的页面 } driver = webdriver.Remote(server, desired_capabilities) wdw = WebDriverWait(driver, 10, 1) tc = TouchAction(driver) tc.press(x=120, y=418)\ .move_to(x=360, y=418)\ .move_to(x=601, y=418)\ .move_to(x=600, y=656)\ .move_to(x=360, y=665)\ .move_to(x=360, y=895)\ .move_to(x=120, y=650)\ .release()\ .perform()
ps:这里需要注意一点,用UIAutomatorViewer工具找各个点的坐标找不到,这时候要用什么找呢?可以打开手机的开发者模式,用手机自带的指针位置功能。
打开方式:
进入设置->关于手机->多次点击版本号,就打开了开发者模式,找到”开发者选项”,按照图示打开:
move_to需要注意:
tc.press(x=120, y=418).wait(1000).move_to(x=360, y=418).release().perform()
tc.press(x=120, y=418).move_to(x=360, y=418).wait(1000).release().perform()
上面这两种写法,wait放置的地方不同,move_to出来的结果有可能不一样,上面这种写法就可以,下面那个就会滑偏,原因:第一个写法是因为脚本直接转换成了swipe的操作,认为是从哪里滑动到哪里,坐标点都是绝对坐标。
第二种写法会被认为是相对坐标,第二个坐标点就被appium改成相对于前面的坐标点的坐标了。
appium1.8版本以上的应该就不会这样了,两种写法都是按照绝对坐标去滑动。
3.7针对手机操作的API
3.7.1获取手机时间
device_time:
print(driver.device_time)
返回时间:2020-01-31T22:04:54+08:00
3.7.2获取手机分辨率
get_window_size():
print(driver.get_window_size())
返回一个字典:{'width': 720, 'height': 1280}
3.7.3打开通知栏
open_notifications():
driver.open_notifications()
关闭的话点击手机的返回就可以
3.7.4返回网络的连接类型
network_connection:
'''返回一个指定网络连接类型的整数位掩码(android)''',即下面的方法里面提到的数字
用法:driver.network_connection
3.7.5设置网络的连接(android)
set_network_connection(connectionType):
这个方法的参数可以直接写,0、1、2、4、6这几个数字,也可以写具体名如下:
NO_CONNECTION = 0
AIRPLANE_MODE = 1
WIFI_ONLY = 2
DATA_ONLY = 4
ALL_NETWORK_ON = 6
比如:
driver.set_network_connection(1)
等同于
driver.set_network_connection(ConnectionType.ALL_NETWORK_ON)
3.7.6截图
get_screenshot_as_file(路径):
把当前的页面截图放到对应路径中。
截图的方法:
driver.get_screenshot_as_file(“../xxx.png”)
比如出现bug的时候可以截图,或者有一些输入需要确认是否输入正确等都可以截图等case执行完毕后确认。
3.7.7检查app是否已安装
is_app_installed:
driver.is_app_installed("com.android.xxx")
3.7.8安装app
install_app:
driver.install_app(app_path)
3.7.9删除app
remove_app:
driver.remove_app(app_path)
3.7.10关掉app
close_app:
driver.close_app ()
3.7.11 keyevent()方法,通过keycode操作手机
keyevent(keycode):
driver.keyevent(24) # 音量加
如果在连接手机的代码里面,有automationName=’Uiautomator2’这样的配置,则应该使用下面这个指令:
press_keycode(keycode)
driver.press_keycode(24) # 音量加
3.7.12 keycode列表
基本按键
KEYCODE名称 |
按键 |
keycode |
KEYCODE_0 |
按键'0' |
7 |
KEYCODE_1 |
按键'1' |
8 |
KEYCODE_2 |
按键'2' |
9 |
KEYCODE_3 |
按键'3' |
10 |
KEYCODE_4 |
按键'4' |
11 |
KEYCODE_5 |
按键'5' |
12 |
KEYCODE_6 |
按键'6' |
13 |
KEYCODE_7 |
按键'7' |
14 |
KEYCODE_8 |
按键'8' |
15 |
KEYCODE_9 |
按键'9' |
16 |
KEYCODE_A |
按键'A' |
29 |
KEYCODE_B |
按键'B' |
30 |
KEYCODE_C |
按键'C' |
31 |
KEYCODE_D |
按键'D' |
32 |
KEYCODE_E |
按键'E' |
33 |
KEYCODE_F |
按键'F' |
34 |
KEYCODE_G |
按键'G' |
35 |
KEYCODE_H |
按键'H' |
36 |
KEYCODE_I |
按键'I' |
37 |
KEYCODE_J |
按键'J' |
38 |
KEYCODE_K |
按键'K' |
39 |
KEYCODE_L |
按键'L' |
40 |
KEYCODE_M |
按键'M' |
41 |
KEYCODE_N |
按键'N' |
42 |
KEYCODE_O |
按键'O' |
43 |
KEYCODE_P |
按键'P' |
44 |
KEYCODE_Q |
按键'Q' |
45 |
KEYCODE_R |
按键'R' |
46 |
KEYCODE_S |
按键'S' |
47 |
KEYCODE_T |
按键'T' |
48 |
KEYCODE_U |
按键'U' |
49 |
KEYCODE_V |
按键'V' |
50 |
KEYCODE_W |
按键'W' |
51 |
KEYCODE_X |
按键'X' |
52 |
KEYCODE_Y |
按键'Y' |
53 |
KEYCODE_Z |
按键'Z' |
54 |
手柄按键
KEYCODE_BUTTON_1 |
通用游戏手柄按钮#1 |
188 |
KEYCODE_BUTTON_2 |
通用游戏手柄按钮 #2 |
189 |
KEYCODE_BUTTON_3 |
通用游戏手柄按钮 #3 |
190 |
KEYCODE_BUTTON_4 |
通用游戏手柄按钮 #4 |
191 |
KEYCODE_BUTTON_5 |
通用游戏手柄按钮 #5 |
192 |
KEYCODE_BUTTON_6 |
通用游戏手柄按钮 #6 |
193 |
KEYCODE_BUTTON_7 |
通用游戏手柄按钮 #7 |
194 |
KEYCODE_BUTTON_8 |
通用游戏手柄按钮 #8 |
195 |
KEYCODE_BUTTON_9 |
通用游戏手柄按钮 #9 |
196 |
KEYCODE_BUTTON_10 |
通用游戏手柄按钮 #10 |
197 |
KEYCODE_BUTTON_11 |
通用游戏手柄按钮 #11 |
198 |
KEYCODE_BUTTON_12 |
通用游戏手柄按钮 #12 |
199 |
KEYCODE_BUTTON_13 |
通用游戏手柄按钮 #13 |
200 |
KEYCODE_BUTTON_14 |
通用游戏手柄按钮 #14 |
201 |
KEYCODE_BUTTON_15 |
通用游戏手柄按钮 #15 |
202 |
KEYCODE_BUTTON_16 |
通用游戏手柄按钮 #16 |
203 |
KEYCODE_BUTTON_A |
游戏手柄按钮 A |
96 |
KEYCODE_BUTTON_B |
游戏手柄按钮 B |
97 |
KEYCODE_BUTTON_C |
游戏手柄按钮 C |
98 |
KEYCODE_BUTTON_X |
游戏手柄按钮 X |
99 |
KEYCODE_BUTTON_Y |
游戏手柄按钮 Y |
100 |
KEYCODE_BUTTON_Z |
游戏手柄按钮 Z |
101 |
KEYCODE_BUTTON_L1 |
游戏手柄按钮 L1 |
102 |
KEYCODE_BUTTON_L2 |
游戏手柄按钮 L2 |
104 |
KEYCODE_BUTTON_R1 |
游戏手柄按钮 R1 |
103 |
KEYCODE_BUTTON_R2 |
游戏手柄按钮 R2 |
105 |
KEYCODE_BUTTON_MODE |
游戏手柄按钮 Mode |
110 |
KEYCODE_BUTTON_SELECT |
游戏手柄按钮 Select |
109 |
KEYCODE_BUTTON_START |
游戏手柄按钮 Start |
108 |
KEYCODE_BUTTON_THUMBL |
Left Thumb Button |
106 |
KEYCODE_BUTTON_THUMBR |
Right Thumb Button |
107 |
电话按键
KEYCODE_CALL |
拨号键 |
5 |
KEYCODE_ENDCALL |
挂机键 |
6 |
KEYCODE_HOME |
按键Home |
3 |
KEYCODE_MENU |
菜单键 |
82 |
KEYCODE_BACK |
返回键 |
4 |
KEYCODE_SEARCH |
搜索键 |
84 |
KEYCODE_CAMERA |
拍照键 |
27 |
KEYCODE_FOCUS |
拍照对焦键 |
80 |
KEYCODE_POWER |
电源键 |
26 |
KEYCODE_NOTIFICATION |
通知键 |
83 |
KEYCODE_MUTE |
话筒静音键 |
91 |
KEYCODE_VOLUME_MUTE |
扬声器静音键 |
164 |
KEYCODE_VOLUME_UP |
音量增加键 |
24 |
KEYCODE_VOLUME_DOWN |
音量减小键 |
25 |
控制按键
KEYCODE_ENTER |
回车键 |
66 |
KEYCODE_ESCAPE |
ESC键 |
111 |
KEYCODE_DPAD_CENTER |
导航键 确定键 |
23 |
KEYCODE_DPAD_UP |
导航键 向上 |
19 |
KEYCODE_DPAD_DOWN |
导航键 向下 |
20 |
KEYCODE_DPAD_LEFT |
导航键 向左 |
21 |
KEYCODE_DPAD_RIGHT |
导航键 向右 |
22 |
KEYCODE_MOVE_HOME |
光标移动到开始键 |
122 |
KEYCODE_MOVE_END |
光标移动到末尾键 |
123 |
KEYCODE_PAGE_UP |
向上翻页键 |
92 |
KEYCODE_PAGE_DOWN |
向下翻页键 |
93 |
KEYCODE_DEL |
退格键 |
67 |
KEYCODE_FORWARD_DEL |
删除键 |
112 |
KEYCODE_INSERT |
插入键 |
124 |
KEYCODE_TAB |
Tab键 |
61 |
KEYCODE_NUM_LOCK |
小键盘锁 |
143 |
KEYCODE_CAPS_LOCK |
大写锁定键 |
115 |
KEYCODE_BREAK |
Break/Pause键 |
121 |
KEYCODE_SCROLL_LOCK |
滚动锁定键 |
116 |
KEYCODE_ZOOM_IN |
放大键 |
168 |
KEYCODE_ZOOM_OUT |
缩小键 |
169 |
组合键
KEYCODE_ALT_LEFT |
Alt+Left |
57 |
KEYCODE_ALT_RIGHT |
Alt+Right |
58 |
KEYCODE_CTRL_LEFT |
Control+Left |
113 |
KEYCODE_CTRL_RIGHT |
Control+Right |
114 |
KEYCODE_SHIFT_LEFT |
Shift+Left |
59 |
KEYCODE_SHIFT_RIGHT |
Shift+Right |
60 |
符号
KEYCODE_PLUS |
按键'+' |
81 |
KEYCODE_MINUS |
按键'-' |
69 |
KEYCODE_STAR |
按键'*' |
17 |
KEYCODE_SLASH |
按键'/' |
76 |
KEYCODE_EQUALS |
按键'=' |
70 |
KEYCODE_AT |
按键'@' |
77 |
KEYCODE_POUND |
按键'#' |
18 |
KEYCODE_APOSTROPHE |
按键''' (单引号) |
75 |
KEYCODE_BACKSLASH |
按键'\' |
73 |
KEYCODE_COMMA |
按键',' |
55 |
KEYCODE_PERIOD |
按键'.' |
56 |
KEYCODE_LEFT_BRACKET |
按键'[' |
71 |
KEYCODE_RIGHT_BRACKET |
按键']' |
72 |
KEYCODE_SEMICOLON |
按键';' |
74 |
KEYCODE_GRAVE |
按键'`' |
68 |
KEYCODE_SPACE |
空格键 |
62 |
小键盘
KEYCODE_NUMPAD_0 |
小键盘按键'0' |
144 |
KEYCODE_NUMPAD_1 |
小键盘按键'1' |
145 |
KEYCODE_NUMPAD_2 |
小键盘按键'2' |
146 |
KEYCODE_NUMPAD_3 |
小键盘按键'3' |
147 |
KEYCODE_NUMPAD_4 |
小键盘按键'4' |
148 |
KEYCODE_NUMPAD_5 |
小键盘按键'5' |
149 |
KEYCODE_NUMPAD_6 |
小键盘按键'6' |
150 |
KEYCODE_NUMPAD_7 |
小键盘按键'7' |
151 |
KEYCODE_NUMPAD_8 |
小键盘按键'8' |
152 |
KEYCODE_NUMPAD_9 |
小键盘按键'9' |
153 |
KEYCODE_NUMPAD_ADD |
小键盘按键'+' |
157 |
KEYCODE_NUMPAD_SUBTRACT |
小键盘按键'-' |
156 |
KEYCODE_NUMPAD_MULTIPLY |
小键盘按键'*' |
155 |
KEYCODE_NUMPAD_DIVIDE |
小键盘按键'/' |
154 |
KEYCODE_NUMPAD_EQUALS |
小键盘按键'=' |
161 |
KEYCODE_NUMPAD_COMMA |
小键盘按键',' |
159 |
KEYCODE_NUMPAD_DOT |
小键盘按键'.' |
158 |
KEYCODE_NUMPAD_LEFT_PAREN |
小键盘按键'(' |
162 |
KEYCODE_NUMPAD_RIGHT_PAREN |
小键盘按键')' |
163 |
KEYCODE_NUMPAD_ENTER |
小键盘按键回车 |
160 |
功能键
KEYCODE_F1 |
按键F1 |
131 |
KEYCODE_F2 |
按键F2 |
132 |
KEYCODE_F3 |
按键F3 |
133 |
KEYCODE_F4 |
按键F4 |
134 |
KEYCODE_F5 |
按键F5 |
135 |
KEYCODE_F6 |
按键F6 |
136 |
KEYCODE_F7 |
按键F7 |
137 |
KEYCODE_F8 |
按键F8 |
138 |
KEYCODE_F9 |
按键F9 |
139 |
KEYCODE_F10 |
按键F10 |
140 |
KEYCODE_F11 |
按键F11 |
141 |
KEYCODE_F12 |
按键F12 |
142 |
多媒体键
KEYCODE_MEDIA_PLAY |
多媒体键 播放 |
126 |
KEYCODE_MEDIA_STOP |
多媒体键 停止 |
86 |
KEYCODE_MEDIA_PAUSE |
多媒体键 暂停 |
127 |
KEYCODE_MEDIA_PLAY_PAUSE |
多媒体键 播放/暂停 |
85 |
KEYCODE_MEDIA_FAST_FORWARD |
多媒体键 快进 |
90 |
KEYCODE_MEDIA_REWIND |
多媒体键 快退 |
89 |
KEYCODE_MEDIA_NEXT |
多媒体键 下一首 |
87 |
KEYCODE_MEDIA_PREVIOUS |
多媒体键 上一首 |
88 |
KEYCODE_MEDIA_CLOSE |
多媒体键 关闭 |
128 |
KEYCODE_MEDIA_EJECT |
多媒体键 弹出 |
129 |
KEYCODE_MEDIA_RECORD |
多媒体键 录音 |
130 |
其他
KEYCODE_NUM |
按键Number modifier |
78 |
KEYCODE_INFO |
按键Info |
165 |
KEYCODE_APP_SWITCH |
按键App switch |
187 |
KEYCODE_BOOKMARK |
按键Bookmark |
174 |
KEYCODE_AVR_INPUT |
按键A/V Receiver input |
182 |
KEYCODE_AVR_POWER |
按键A/V Receiver power |
181 |
KEYCODE_CAPTIONS |
按键Toggle captions |
175 |
KEYCODE_CHANNEL_DOWN |
按键Channel down |
167 |
KEYCODE_CHANNEL_UP |
按键Channel up |
166 |
KEYCODE_CLEAR |
按键Clear |
28 |
KEYCODE_DVR |
按键DVR |
173 |
KEYCODE_ENVELOPE |
按键Envelope special function |
65 |
KEYCODE_EXPLORER |
按键Explorer special function |
64 |
KEYCODE_FORWARD |
按键Forward |
125 |
KEYCODE_FORWARD_DEL |
按键Forward Delete |
112 |
KEYCODE_FUNCTION |
按键Function modifier |
119 |
KEYCODE_GUIDE |
按键Guide |
172 |
KEYCODE_HEADSETHOOK |
按键Headset Hook |
79 |
KEYCODE_META_LEFT |
按键Left Meta modifier |
117 |
KEYCODE_META_RIGHT |
按键Right Meta modifier |
118 |
KEYCODE_PICTSYMBOLS |
按键Picture Symbols modifier |
94 |
KEYCODE_PROG_BLUE |
按键Blue “programmable” |
186 |
KEYCODE_PROG_GREEN |
按键Green “programmable” |
184 |
KEYCODE_PROG_RED |
按键Red “programmable” |
183 |
KEYCODE_PROG_YELLOW |
按键Yellow “programmable” |
185 |
KEYCODE_SETTINGS |
按键Settings |
176 |
KEYCODE_SOFT_LEFT |
按键Soft Left |
1 |
KEYCODE_SOFT_RIGHT |
按键Soft Right |
2 |
KEYCODE_STB_INPUT |
按键Set-top-box input |
180 |
KEYCODE_STB_POWER |
按键Set-top-box power |
179 |
KEYCODE_SWITCH_CHARSET |
按键Switch Charset modifier |
95 |
KEYCODE_SYM |
按键Symbol modifier |
63 |
KEYCODE_SYSRQ |
按键System Request / Print Screen |
120 |
KEYCODE_TV |
按键TV |
170 |
KEYCODE_TV_INPUT |
按键TV input |
178 |
KEYCODE_TV_POWER |
按键TV power |
177 |
KEYCODE_WINDOW |
按键Window |
171 |
KEYCODE_UNKNOWN |
未知按键 |
0 |
appium移动自动化详解的更多相关文章
- APP 自动化之手势操作appium提供API详解(四)
一.手势操作1.上下左右滑屏 swipe---滑动 java-client 4.x 是有swipe方法的,可以通过传递坐标信息就可以完成滑动androidDriver.swipe(startx, st ...
- 『与善仁』Appium基础 — 12、Appium的安装详解
目录 (一)Appium server安装 方式一:(桌面方式:推荐) 1.Appium Desktop下载 2.Appium Desktop安装 3.Appium Desktop使用 方式二:(No ...
- Appium+python自动化(三十)- 实现代码与数据分离 - 数据配置-yaml(超详解)
简介 本篇文章主要介绍了python中yaml配置文件模块的使用让其完成数据和代码的分离,宏哥觉得挺不错的,于是就义无反顾地分享给大家,也给大家做个参考.一起跟随宏哥过来看看吧. 思考问题 前面我们配 ...
- Appium+python自动化(十六)- ADB命令,知否知否,应是必知必会(超详解)
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态. adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或 ...
- appium+java(二)appium初始化参数部分详解
Capabilities介绍 实际上它的全称是:Desired capabilities Desired capability是一个JSON对象,包含一组key和value值.它由客户端发送给服务端, ...
- python WEB接口自动化测试之requests库详解
由于web接口自动化测试需要用到python的第三方库--requests库,运用requests库可以模拟发送http请求,再结合unittest测试框架,就能完成web接口自动化测试. 所以笔者今 ...
- 自动化运维工具——ansible详解(一)
ansible 简介 ansible 是什么? ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.chef.func.fabric)的优点,实现了批量系统 ...
- 自动化运维工具——puppet详解(一)
一.puppet 介绍 1.puppet是什么 puppet是一个IT基础设施自动化管理工具,它能够帮助系统管理员管理基础设施的整个生命周期: 供应(provisioning).配置(configur ...
- Web自动化框架LazyUI使用手册(3)--单个xpath抓取插件详解(selenium元素抓取,有此插件,便再无所求!)
概述 前面的一篇博文粗略介绍了基于lazyUI的第一个demo,本文将详细描述此工具的设计和使用. 元素获取插件:LazyUI Elements Extractor,作为Chrome插件,用于抓取页面 ...
随机推荐
- js事件节流
背景:在监听浏览器滚动条的scroll事件时该事件会触发很多次,这样当快速滚动时会有很差的性能,所以要限制事件触发的频率,可以防抖和节流,这里我记录简单的节流方法 <!DOCTYPE html& ...
- 吴裕雄--天生自然KITTEN编程:躲迷藏
- 关于sql拼接的知识点 where1=1
String sql="select * from tab_route where 1 = 1 "; 这样不会报错,而且可以根据情况,再去拼接sql 可以使用if(){}else{ ...
- 使用itchat发送天气信息
微信发送当日天气情况 念头萌生 之前在浏览网站的时候发现了篇文章「玩转树莓派」为女朋友打造一款智能语音闹钟,文章中介绍了使用树莓派打造一款语音播报天气的闹钟. 当时就想照着来,也自己做个闹钟.因为一直 ...
- http 详解
HTTP协议中GET.POST和HEAD的介绍 GET: 请求指定的页面信息,并返回实体主体. HEAD: 只请求页面的首部. POST: 请求服务器接受所指定的文档作为对所标识的URI的新的从属实体 ...
- C++扬帆远航——2
/* * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:test.cpp * 作者:常轩 * 完成日期:2016年3月6 ...
- 爬虫(一)爬取鱼c淘贴信息
掏出了以前的小练习: 现在开始,每天复习下以前的爬虫练习,争取发现新的问题和可以优化的地方. # -*- coding:utf-8 -*- import requests import chardet ...
- 压力测试(二)-Jmeter基本介绍
1.Jmeter基本介绍和使用场景 简介 1.压测不同的协议和应用 1) Web - HTTP, HTTPS (Java, NodeJS, PHP, ASP.NET, …) 2) SOAP / RES ...
- dom节点及对节点的常用操作方法
dom节点及对节点的常用操作方法 在说dom节点前,先来看看页面的呈现: dom渲染流程: 1.浏览器解析html源码,然后创建一个DOM树. 在DOM树中,每一个HTML标签都有一个对应的节点(元 ...
- disruptor 入门 一
一.disruptor基本概念 https://www.cnblogs.com/haiq/p/4112689.html 二.disruptor入门程序 导入disruptor包 <depende ...