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 |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 一文详解Ansible自动化运维
- vue-cli 自动化测试 Nightwatch 详解
- 利用expect命令实现Shell自动化交互的方法详解
- ansible自动化运维详细教程及playbook详解
- 别让运维太忙,一文详解 Ansible 的自动化运维
- Node.js开发多端自动化步骤详解(Windows,Mobile,Web)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Programming Computer Vision with Python
Jan Erik Solem / O'Reilly Media / 2012-6-22 / USD 39.99
If you want a basic understanding of computer vision's underlying theory and algorithms, this hands-on introduction is the ideal place to start. As a student, researcher, hacker, or enthusiast, you'll......一起来看看 《Programming Computer Vision with Python》 这本书的介绍吧!