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)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Book of CSS3
Peter Gasston / No Starch Press / 2011-5-13 / USD 34.95
CSS3 is the technology behind most of the eye-catching visuals on the Web today, but the official documentation can be dry and hard to follow. Luckily, The Book of CSS3 distills the heady technical la......一起来看看 《The Book of CSS3》 这本书的介绍吧!