分类 未分类 下的文章
专利申请的一些事宜
今天跟专利公司聊了一下,了解一些申请相关的事情。
发明专利申请看“三性”、实用性、新颖性、创造性。
- 实用性来说,只要能做出个产品用的就是实用的,一般问题不大;
- 新颖性呢,也很少在这一点上被驳回,专利公司帮着查也最多是新颖性稍微看一下而已;
- 创造性,这一点是最多被驳回的理由,可是专利公司又很难把握,一个发明够新颖,但是不是有足够的创造性,可以和其他的发明区分,只能看实审了;
另外,讲了一下什么是“双申请”。双申请就是一个专利同时申请实用新型和发明专利。实用新型申请下来快,有保障,发明申请慢,可能会被驳回。但发明专利获得授权时,必须先放弃实用新型的授权。这样,一个发明专利的申请过程就变成:双申请->实用新型申请通过->发放实用新型授权书->发明专利初审实审->发明专利授权通过->放弃实用新型授权->获得发明专利授权
。
专利费用
发明专利,根据专利公司的口径,代理费5000,官费的话,如果能申请税减,则为560(估计是按85%减,135+375+50,参见下面的官费明细表),不能申请则为3450(900+2500+50)。
对额外的权利要求,官费会另收,,权利要求超过 10 项的,加收官费 RMB150 元/项;说明书 超过 30 页的,加收官费 RMB50 元/页。
国家知识产权局官费--费用明细表
实用新型和外观专利会有新颖性的审查代理费,每件1500。
补贴方面:
- 深圳市进入实审阶段,如果有税减则补贴510,没有则补贴2000;拿到授权再补贴3000.
- 南山区以前进入实审阶段,会补贴2500,2018年可能改为授权后补贴10000,不在对实审补贴,具体未定。代理公司代办会收取10%费用。
3D传感技术
苹果 ARKit
安卓 ARCore
单目相机跟踪
安卓 Tango
需要ToF相机辅助,使用此技术的手机: 联想 Phab 2 Pro,还有华硕Zenfone AR手机。
这个技术2017年上半年发布,可是2018年3月1日就要停了。官网在这儿
官网上说,google将转去做不需要特殊硬件的ARCore。google还特别说了一下华硕的Zenfone AR手机用户,以后会告诉你们这些用tango的怎么转去用ARCore...这个项目就这么悲催了...
微软 Kinect
Kinect For Windows的开发页面
官网页面说明,Kinect硬件已经停产,只是其技术奖用于HoloLens、小娜语音助手、Hello生物面部识别、还有一个上下文感知UI界面。已经在开发Kinect的程序员,微软推荐转移到Intel的RealSense深度相机上去。
Kinect的好处是价格便宜。只要200多,要不在最终买不到前先弄一套。。。
Kinect v1用于 xbox360, v2用于xbox one,v2比v1提升了很多。具体可以看:XBOX之Kinect1与2的区别, 【翻译】Kinect v1和Kinect v2的彻底比较
从技术上来说,V1是以色列的PrimeSense开发的技术,也就是结构光,该公司在2013年被苹果收购,开发了iPhone X的FaceID上用的TrueDepth……悲剧了……不知道是不是因为这个原因,V2改用了ToF技术。
所以V2并不兼容V1的SDK……
微软收购了3DV公司,就是做ToF技术的。
intel RealSense深度相机
Intel RealSense主页,这个相机目前价格超贵,淘宝查出来要1000~2000元。
据知乎上的人说,RealSense主要检测上半身,适用于在桌面上使用。估计是为了卖笔记本,哈哈。
ToF 传感器(相机),Time of Flight
结构光3D传感器
苹果称之为 TrueDepth,iPhone X前置FaceID解决方案,结构光 3D 传感器
以色列PrimeSense开发,以前也是微软的Kinect的方案提供方。
不过通过github查询到似乎与这家公司有关的另一家独立公司occipital,有卖结构光传感器,单卖379美元,整套499美元,我靠真贵。
硬件开发也能敏捷?
参考文章:硬件也敏捷!
硬件的敏捷,主要是在原型阶段,努力做到:
- 尽快交付可用件,这时候PCB可能是用开发板做的,也可以为了验证硬件的正确性开发测试固件、软件,而测试固件和软件的开发都可以使用敏捷;
- 尽快测试,并尽可能做到可测试,这可以找最终用户或者最接近最终用户的内部团队来做;
- 设计时考虑如何测试(TDD),或者尽可能做可以测试的设计;
- 划分松耦合的模块很重要,将事情化成小块,有利于每一块的快速迭代;
硬件初创公司制造产品还有哪些障碍?
当"工匠"遭遇工人:需重拾对制造业的敬畏
智能硬件创业有多难?从土曼科技T-Fire手表的跳票说起
[Top 10 questions when using Agile on hardware projects](http://maccherone.com/larry/2010/02/23/top-10-questions-when-using-agile-on-hardware-projects/
能否在硬件项目中应用敏捷方法?
gene
场
标量场
可用大小完全表征,如温度场、湿度场、浓度场、密度场……
矢量场
还需要大小加方向加以表征。
保守场
矢量场的一种,此矢量场是标量势的梯度。
一个矢量场V 称为保守的,即如果存在一个标量场φ,使得V=▽φ。在这里▽φ表示φ的梯度。当以上的等式成立时,φ就称为V的一个标量势。
保守场的第二类曲线积分只与起点和终点有关,而与路径无关。
判断方式就是,从场中一点到另一点,如论路线如何,结果都一样。如重力场和静电场,从一点到另一点无论路线如何,所做的功都一样。
无旋场
旋度处处为零
有旋场
旋度并非处处为零
静电场是有源无旋场,电流流经导体为无源有旋场,磁场为无源有旋场。
电磁波分类
序号 | 类别/波名 | 简称 | 名称 | 频率Hz | 波长 米 | 能量 eV |
---|---|---|---|---|---|---|
1 | 电离辐射 | γ | 伽马射线 Gamma rays | 3e20~3e19 | 1e-12~1e-11 | 1.24e6~1.24e5 |
2 | 电离辐射 | HX | 硬X射线 Hard X rays | 3e19~ | 1e-11~ | 1.24e5~ |
3 | 电离辐射 | SX | 软X射线 Soft X rays(跨2个数量级) | 3e18~ | 1e-10~ | 1.24e4~ |
4 | 电离辐射 | EUV | 超紫外 Extreme ultraviolet | 3e16~ | 1e-8~ | 1.24e2~ |
5 | 可见光 | NUV | 近紫外 Near ultraviolet | 3e15~ | 1e-7~ | 1.24e1~ |
6 | 可见光 | NIR | 近红外 Near infrared | 3e14~ | 1e-6~ | 1.24~ |
7 | (空) | MIR | 中红外 Mid infrared | 3e13~ | 1e-5~ | 1.24e-1~ |
8 | (空) | FIR | 远红外 Far infrared | 3e12~ | 1e-4~ | 1.24e-2~ |
9 | 微波:毫米波 | EHF | 极高频 Extremely high frequency | 3e11~ | 1e-3~ | 1.24e-3~ |
10 | 微波:厘米波 | SHF | 超高频 Super high frequency | 3e10~ | 1e-2~ | 1.24e-4~ |
11 | 微波:分米波 | UHF | 特高频 Ultra high frequency | 3e9~ | 1e-1~ | 1.24e-5~ |
12 | 米波/超短波 | VHF | 甚高频 Very high frequency | 3e8~ | 1~ | 1.24e-6~ |
13 | 短波 | HF | 高频 High frequency | 3e7~ | 1e1~ | 1.24e-7~ |
14 | 中波 | MF | 中频 Medium frequency | 3e6~ | 1e2~ | 1.24e-8~ |
15 | 长波 | LF | 低频 Low frequency | 3e5~ | 1e3~ | 1.24e-9~ |
16 | 甚长波 | VLF | 甚低频 Very low frequency | 3e4~ | 1e4~ | 1.24e-10~ |
17 | 特长波 | ULF | 特低频 Ultra low frequency | 3e3~ | 1e5~ | 1.24e-11~ |
18 | 超长波 | SLF | 超低频 Super low frequency | 3e2~ | 1e6~ | 1.24e-12~ |
19 | 极长波 | ELF | 极低频 Extremely low frequency | 3e1~3 | 1e7~ | 1.24e-13~ |
工频50~60Hz属于超低频
无线电波3000米~0.3毫米(微波0.1~100厘米)
红外线0.3毫米~0.75微米(其中:近红外为0.76~3微米,中红外为3~6微米,远红外为6~15微米,超远红外为15~300微米)
可见光0.7微米~0.4微米
紫外线0.4微米~10纳米
X射线10纳米~0.1纳米
γ射线0.1纳米~1皮米
高能射线小于1皮米
传真(电视)用的波长是3~6米
雷达用的波长在3米到几毫米。
这篇文章有很多电磁波动图,可以作参考
常见数字前缀
Symbol | Prefix | Exponent |
---|---|---|
y | yocto- | (10)-24 夭 |
z | zepto- | (10)-21 泽 |
a | atto- | (10)-18 阿(托) |
f | femto- | (10)-15 飞(母托), 毫微微 |
p | pico- | (10)-12 皮(可),微微 |
n | nano- | (10)-9 纳(诺),毫微 |
u | micro- | (10)-6 微 |
m | milli- | (10)-3 毫 |
无前缀 | 无前缀 | (10)0 |
k | kilo- | (10)3 千 |
M | mega- | (10)6 兆 |
G | giga- | (10)9 吉 |
T | tera- | (10)12 太 |
P | peta- | (10)15 拍 |
E | exa- | (10)18 艾(克沙) |
Z | zetta- | (10)21 泽 |
Y | yotta- | (10)24 尧 |
注意:字母大小写的区别。正指数的前缀,大多含有“a”的字符音元;而负指数的前缀,大多含有“o”的字符音元。
补充一点:正指数的前缀符号中,多数符号大写,唯代表kilo的符号“k”是小写,以区别于代表温度的符号:大写的“K” 。
十、百、千、兆、吉、太、拍、艾、泽、尧。 千以前是十进位,千以后是千进位。 分、厘、毫、微、纳、皮、飞、阿、仄、夭。
阅读(9145)| 评论(0)
linux上抓无线包
需要linux系统, kali最好,自带很多网络监听工具.
在windows上安装虚拟机, 试过Virtualbox和VMWare, 只有VMware是正常的(VMWare Workstation 11)
需要一个可以监听的硬件,试过这款可以Ralink RT5370 150M USB迷你无线网卡 机顶盒WIFI信号发射接收器,价格也只有17元.
这个也可以, 只是太贵,要100多.包邮TP-LINK WN722N V1 AR9271A无线渗透usb无线网卡LINUX 免驱动. 可以搜索AR9271,找到更便宜一些的.
Grav CMS太吃存储空间
今天登陆后台发现, grav现在已经占了100多M的空间,我还没有上传1张图片...这看起来比使用数据库的wordpress耗费的存储要多得多.
安卓上安装linux
参考文章 Convert-an-Android-Device-to-Linux
- busybox可以模拟部分linux指令和操作, 但毕竟不是linux
- Termux更像是linux, 有自己的包管理,能装node, python, 而且不需要root,但工作起来毕竟还是受限
- 要装任意linux发行版,怎么办, 可以安装Linux Depoly或者Complete Linux Installer
- 还可以装模拟器Limbo PC Emulator
FreeRTOS基础(包括ESP8266)
根据网上的中文版《FreeRTOS实时内核实用指南》,主要有这几部分内容
- 任务调度。可以创建多个任务(xTaskCreate),然后启动调度器(vTaskStartScheduler)根据优先级进行调度
- 消息队列。任务间通讯通过消息队列完成。
- 中断管理。
- 资源管理。主要是独占资源如何在多任务中进行管理。
- 内存管理。
其实核心是多任务。
根据ESP8266 FreeRTOS的指南,可以完成如下事项:
- 常规的WIFI操作,如AP、Station、混杂模式Sniffer等
- spiffs,spi flash文件系统
- SSC, 简单串口命令注册和使用,可通过串口发送命令和解析
- 系统的启动与升级
python实现getch()效果
在windows上比较简单:
import msvcrt
ch = msvcrt.getch()
其他平台,可以安装getch模块
pip install getch
然后
import getch
# ...
char = getch.getch() # User input, but not displayed on the screen
# or
char = getch.getche() # also displayed on the screen
如何重定向网站
本网站[idarc.cn]使用了dns解析服务器上设置显性URL的方式来将二级域名grav.idarc.cn进行重定向到 idarc.cn/grav, 但对于主域名idarc.cn也想重定向到idarc.cn/grav上, 这儿有一篇很好很详细的文章:How to Redirect a Web Page
由于我是托管在php主机上, 所以无法随意改主机服务器的设置, 只能修改网页. 我使用了JavaScript的window.location转向的方式, 但似乎搜索引擎只有google能搜索出来, 而百度和bing都不行. 下来试试meta的效果看如何:
<meta http-equiv="refresh" content="0; URL='http://new-website.com'" />
Appium入门
2020-2-21更新
很多次想搞一搞android的自动化界面测试, 这下开始啦!
主要参考的Appium官方文档:
失效文档
Android文档
- Android UiSelector文档
警告!UiSelector已经被弃用, 改为了AndroidX:com.android.support.test.uiautomator:uiautomator
转移为androidx.test.uiautomator:uiautomator
, 新的文档地址 - Android Keycode文档
- npm keycode-for-android, 如果没有这个库,你只好去查android keyevent文档了,自己写,自己传自己用^_^
wd.js文档
Webdriver文档
1. Appium分为server和client, server需要先运行. client用于跑脚本.
在windows上用appium server, 可以用node安装或者安装Desktop版本. 推荐安装Desktop版本,下载地址在github上
node安装方式:
npm install -g appium
appium
可惜的是, 他需要从googleapis下载一个chromedriver的包, 你知道的,这是不可能的, 所以会一直卡在这儿:
npm install -g appium
C:\Users\Jac\AppData\Roaming\npm\appium -> C:\Users\Jac\AppData\Roaming\npm\node_modules\appium\build\lib\main.js
> appium-chromedriver@3.0.1 install C:\Users\Jac\AppData\Roaming\npm\node_modules\appium\node_modules\appium-chromedriver
> node install-npm.js
info Chromedriver Install Installing Chromedriver version '2.30' for platform 'win' and architecture '32'
info Chromedriver Install Opening temp file to write chromedriver_win32 to...
info Chromedriver Install Downloading https://chromedriver.storage.googleapis.com/2.30/chromedriver_win32.zip...
这儿你可以使用cmder, 设置代理, 然后再下载.
另外还可以老老实实下载desktop版本试试. 下载地址在github上
2. 调试安卓的准备.
可以看appium的官方文档,步骤还是不少的, 下面简要说一下:
- 下载和安装/解压JDK, 设置JAVA_HOME, 将其中bin目录放到PATH里面
- 安装Android SDK, 设置ANDROID_HOME, 将其中tools和platform-tools目录放到PATH里面
- 安装Apache Ant,或者用android SDK目录下的eclipse\plugins里面那个. 确保能访问ant的目录放入PATH里面
- 安装Apache Maven, 设置M2_HOME为解压目录, M2为bin目录,把bin目录加到PATH里面(PATH里面得多少东西啊, win10的PATH还有2048个字符的限制, 我的已经分分钟要超出了...)
- 连接android设备或者启动个模拟器,API level需要大于等于17.
- 测试脚本需要确认platformVersion与测试设备一致, app项设置地址是到.apk文件的绝对路径
3. 运行测试
-
连接手机
用线连接手机很简单, 要记得点击手机中设置->版本号5次打开开发者模式->打开USB调试. -
连接安卓夜神模拟器
连接安卓夜神模拟器的方式, 先在模拟器设置中把平板模式调成手机模式, 然后再点击手机中设置->版本号5次打开开发者模式->打开USB调试.
然后再命令行输入:adb connect 127.0.0.1:62001
-
adb devices确定连接的设备有且只有一个. 如果有问题, 你可以重启adb:
adb kill-server && adb devices
测试安卓得知道包名和activity名字, 可测试的人儿哪儿知道...好啦有个办法(linux上用grep替代findstr):
adb shell dumpsys window windows | findstr mFocusedApp
我关注的我们isen的输出是这样的:
adb shell dumpsys window windows | findstr isen Window #5 Window{f9a1670 u0 com.isen.trace.police/com.isen.tz.wifitz.activity.MainActivity}: mOwnerUid=10242 mShowToOwnerOnly=true package=com.isen.trace.police addTime=2017-11-24 19:49:12 appop=NONE mToken=AppWindowToken{c40a9b1 token=Token{ca91458 ActivityRecord{471753b u0 com.isen.trace.police/com.isen.tz.wifitz.activity.MainActivity, isShadow:false t129}}} mRootToken=AppWindowToken{c40a9b1 token=Token{ca91458 ActivityRecord{471753b u0 com.isen.trace.police/com.isen.tz.wifitz.activity.MainActivity, isShadow:false t129}}} mAppToken=AppWindowToken{c40a9b1 token=Token{ca91458 ActivityRecord{471753b u0 com.isen.trace.police/com.isen.tz.wifitz.activity.MainActivity, isShadow:false t129}}} WindowStateAnimator{2b01034 com.isen.trace.police/com.isen.tz.wifitz.activity.MainActivity}: mSurface=Surface(name=com.isen.trace.police/com.isen.tz.wifitz.activity.MainActivity) mInteractingStatusBarWindow=Window{f9a1670 u0 com.isen.trace.police/com.isen.tz.wifitz.activity.MainActivity} mCurrentFocus=Window{f9a1670 u0 com.isen.trace.police/com.isen.tz.wifitz.activity.MainActivity} mFocusedApp=AppWindowToken{c40a9b1 token=Token{ca91458 ActivityRecord{471753b u0 com.isen.trace.police/com.isen.tz.wifitz.activity.MainActivity, isShadow:false t129}}} PkgName=com.isen.trace.police
4. 检查一下android环境
前面安装好了appium desktop版的话, 默认也会装一个appium-doctor,可以用来检查环境.我的目录如下:
"C:\Program Files (x86)\Appium\node_modules\.bin\appium-doctor.cmd" --android
Running Android Checks
✔ ANDROID_HOME is set to "C:\Users\Jac\AppData\Local\Android\Sdk"
✔ JAVA_HOME is set to "C:\Program Files\Java\jdk1.8.0_111."
✔ ADB exists at C:\Users\Jac\AppData\Local\Android\Sdk\platform-tools\adb.exe
✔ Android exists at C:\Users\Jac\AppData\Local\Android\Sdk\tools\android.bat
✔ Emulator exists at C:\Users\Jac\AppData\Local\Android\Sdk\tools\emulator.exe
✔ Android Checks were successful.
✔ All Checks were successful
当然你可以用npm装一个,这样就不需要找appium-doctor到底在那个目录了
npm install -g appium-doctor
appium-doctor.cmd --android
info AppiumDoctor Appium Doctor v.1.4.3
info AppiumDoctor ### Diagnostic starting ###
info AppiumDoctor ✔ The Node.js binary was found at: C:\Program Files\nodejs\node.exe
info AppiumDoctor ✔ Node version is 6.10.0
info AppiumDoctor ✔ ANDROID_HOME is set to: C:\Users\Jac\AppData\Local\Android\Sdk
info AppiumDoctor ✔ JAVA_HOME is set to: C:\Program Files\Java\jdk1.8.0_111
info AppiumDoctor ✔ adb exists at: C:\Users\Jac\AppData\Local\Android\Sdk\platform-tools\adb.exe
info AppiumDoctor ✔ android exists at: C:\Users\Jac\AppData\Local\Android\Sdk\tools\android.bat
info AppiumDoctor ✔ emulator exists at: C:\Users\Jac\AppData\Local\Android\Sdk\tools\emulator.exe
info AppiumDoctor ✔ Bin directory of %JAVA_HOME% is set
info AppiumDoctor ### Diagnostic completed, no fix needed. ###
info AppiumDoctor
info AppiumDoctor Everything looks good, bye!
info AppiumDoctor
主要是是 ANDROID_HOME 这个变量, 我的系统里面只设置了一个叫 ANDROID_SDK_ROOT 的变量...不知道是安装那个程序需要的. 内容是一样的.
5. 设置项目
当然是先新建个项目目录,然后npm init了,老规矩,然后安装appium官方推荐的wd.js作为客户端driver, 使用promise的方式.
npm init
npm install -S wd chai chai-as-promised colors
6. 运行服务器
把appium跑起来. 这儿选择桌面版的运行. 运行了以后,看到提示服务器地址 http://127.0.0.1:4723
7. 准备和服务器建立连接前的基础知识
不得不先讲点儿理论了. 就是这个Webdriver和JSONWireProtocol建立了客户端与服务器的会话(Session).
那么Webdriver是什么呢, 说起源头还是Selenium的一部分, 是一个自动化的测试方式, 也就是通过客户端向服务器发命令进行测试的方式, 测试服务器再控制浏览器运行测试命令. 2012年, Webdriver被W3C标准化, 然后也就出现了很多不同的Webdriver的语言实现.
webdriver标准里面定义了服务器客户端使用RestFul API进行交互, 交互的协议称为wire protocol. 数据内容是JSON形式的, 这就是JSONWireProtocol了(也称作Webdriver Wire Protocol). 定义在github这儿.
按照这个定义页面上讲的, JSON Wire Protocol也已经过期, 因此, 目前来看Webdriver标准和JSONWireProtocol, Webdriver Wire Protocol其实就是一个东西在不同时期的叫法不同. 现在来看, 最新叫法就是W3C Webdriver 标准了.
建立连接的步骤分两步:
- 先建立与服务器连接, 这儿需要知道服务器的地址,端口号, 有时候还需要用户名密码. 因为是HTTP RESTful的, 因此可以表示为url形式, 如默认一般是http://localhost:4723
- 再建立session连接. 建立session连接时, 客户端应提供一些基础数据, 称之为能力Capabilities, 简称caps. webdriver最初是用作web测试的, 所以需要填写的内容和Appium用作app测试的有些不同. 测试androidapp, 数据如下(JSON形式):
2020-2-20注: 最新版Appium已经改了很多,详细看: Appium Desired Capabilities{ platformName: "Android", deviceName: "HUAWEI MLA-AL10", appPackage: "com.ss.android.ugc.aweme", //这个是抖音包名,包名可以在设置->应用->运行中的APP查看 appActivity: ".main.MainActivity", //主Activity,也可以在上面的路径查看 automationName: "UiAutomator1", platformVersion: "4.4.2", browserName: "", noReset: "true", //非常重要! 如果不希望清空原APP数据直接启动,这个一定要为true newCommandTimeout: 6000, unicodeKeyboard: "true", //unicodeKeyboard和resetKeyboard非常重要! 设置后才能通过sendKeys发送中文 resetKeyboard: "true" }
newCommandTimeout默认值为60, 意思是60秒无任何命令输入就断掉session. 如果是使用wd shell交互式命令, 或者使用Appium inspector(后面讲), 或者刚刚开始学习的话, 最好设置久一点,以免正看文档着呢, session就没了就无法操作了, 还得花几分钟重启session呢.
后面在常见问题里讲了如果session中断后如何重连的方式.
下面就可以发命令控制了. 控制浏览器的命令就写在Webdriver标准里面, 控制app的命令写在appium文档里面
8. 获得界面元素的工具
界面上很多元素需要获得之后再去操作, H5可以在页面审查,看源码,知道ID和Class什么的用来定位,可是安卓原生应用该怎么办?
两个工具Appium inspector和UIAutomator Viewer
UIAutomator Viewer
先说UIAutomator Viewer(简称UIAV),这个是跟android SDK一起安装的. 我的Windows下位置是:
C:\Users\Jac\AppData\Local\Android\Sdk\tools\uiautomatorviewer.bat
双击后打开, 点击第三个图标"Device Screeshot with compressed Hierarchy".
UIAV的运行与Appium session的运行冲突, 如果报错, 请将Appium 服务停掉, 相关的client session断掉.
然后左侧窗口将显示屏幕截图, 点击图上某一元素右侧会显示属性.
Appium inspector
再说说Appium inspector(以下简称AI), 这是和Appium Desktop版一起安装的. 从界面上我估计这些货都是Electron开发的:)
Appium Desktop的服务器运行后,右上角第一个放大镜按钮点击,打开一个Appium的图形化界面客户端, 在这儿启动session后就会进入AI.
你可以在左侧一行一行的添加caps, 也可以在右侧直接将JSON复制进去并保存. json 格式正确将会成功保存, 格式错误将无法保存, 不过工具目前没有给提示.
输入后点击start session, 等待服务器将必要的app和测试app都装入手机, 将进入Appium inspector.
左侧是截图, 也可以选择元素, 不过位置总不太对. 上面还可以选择录制(眼睛图标), 录制下来的脚本可以选择不同的语言. 不过目前还有很大的问题, wd.js里面有的语法还是写错的...另外, 选择一步操作后,反应还是有些慢.似乎主要都耗时在截图传输上了.
9. 使用AI录制命令
进入AI界面后, 点击录制(start recording)按钮开始录制.
右侧可以选择客户端语言, 以wd.js为例(JS - WD(Promise)). 旁边三个按钮依次是:显示完整代码, 复制代码, 清空代码. 选择滑动, 做一个上滑操作, 显示完整代码, 如下:
// Requires the admc/wd client library
// (npm install wd)
// Then paste this into a .js file and run with Node 7.6+
const wd = require('wd');
const driver = wd.promiseChainRemote("localhost", 4723);
const caps = {"platformName":"android","deviceName":"myphone","app":"C:\\my.apk","browserName":""};
async function main () {
await driver.init(caps);
await (new TouchAction(driver))
.press({x: 326, y: 491})
.moveTo({x: 21: y: -166})
.release()
.perform()
await driver.quit();
}
main().catch(console.log);
注意代码中有两个问题
- moveTo里面的对象格式写错了, 应该是
{x: 21, y: -166}
new TouchAction(driver)
写错, 应该是new wd.TouchAction(driver)
改好以后, 放到项目下的一个js文件里(如test.js), 用node运行node test.js
, node 版本需要大于7.6, 主要是新版node实现了ES7里面的async和await.
10. 使用wd.js的repl界面
wd.js支持repl是个惊喜. 运行方式是在项目目录下面:
.\node_modules\.bin\wd shell
在这儿可以输入wd.js的命令, 进行交互.
因为交互敲命令需要时间,为避免session断开, 可以在caps里面增加一项"newCommandTimeout": 6000
, 延长超时时长(默认60秒)到6000秒.
依次(三条命令分三次)输入如下命令, 达到与代码类似的效果
const wd = require('wd'),
driver = wd.promiseChainRemote("localhost", 4723),
caps = {"platformName":"android","deviceName":"c195b35c","app":"C:\\r\\Appium\\wrtestcases\\apk\\TzRadar_373_v3.7.3_373_jiagu_sign.apk","browserName":"",
"newCommandTimeout": 6000},
TouchAction = wd.TouchAction;
driver.init(caps);
(new TouchAction(driver))
.press({x: 338, y: 716})
.moveTo({x: -5, y: -357})
.release()
.perform();
11. wd.js在appium测试android的时候可以用哪些命令: driver部分
因为不同的测试平台可用的命令不同, 如果敲入了未实现的命令, 就会返回错误.
哪些命令可用? 参考的知识太多, 涉及webdriver, wd.js, appium, android...同时开这几个文档来回切换看好累...实操可用的如下:
//driver可用的命令, cb表示callback函数. 是否可以await尚未测试.
driver.lock(3) //锁定, 3貌似是延时
driver.backgroundApp(5) //后台运行, 5貌似是延时
driver.hideKeyboard()
driver.startActivity({appPackage: 'com.example.android.apis', appActivity: '.Foo'}, cb)
driver.openNotifications(cb);
driver.isAppInstalled("com.example.android.apis")
.then(function (isAppInstalled) { /*...*/ })
driver.installApp("path/to/my.apk")
driver.removeApp("com.example.android.apis")
driver.closeApp()
driver.launchApp()
driver.resetApp()
driver.shake()
driver.contexts().then(function (contexts) { /*...*/ }) //List all available contexts
driver.currentContext().then(function (context) { /*...*/ })
driver.context() //SWITCH TO DEFAULT CONTEXT
driver.getAppStrings().then(function (appStrings) { /*...*/ })
driver.deviceKeyEvent(wd.SPECIAL_KEYS.Home) //send key event
driver.getCurrentActivity().then(function (activity) { /*...*/ })
//swipe
function swipe(opts) {
var action = new wd.TouchAction(this);
action
.press({x: opts.startX, y: opts.startY})
.wait(opts.duration)
.moveTo({x: opts.endX, y: opts.endY})
.release();
return action.perform();
}
wd.addPromiseChainMethod('swipe', swipe);
// pinch
function pinch(el) {
return Q.all([
el.getSize(),
el.getLocation(),
]).then(function(res) {
var size = res[0];
var loc = res[1];
var center = {
x: loc.x + size.width / 2,
y: loc.y + size.height / 2
};
var a1 = new wd.TouchAction(this);
a1.press({el: el, x: center.x, y:center.y - 100}).moveTo({el: el}).release();
var a2 = new wd.TouchAction(this);
a2.press({el: el, x: center.x, y: center.y + 100}).moveTo({el: el}).release();
var m = new wd.MultiAction(this);
m.add(a1, a2);
return m.perform();
}.bind(this));
};
wd.addPromiseChainMethod('pinch', pinch);
wd.addElementPromiseChainMethod('pinch', function() {
return this.browser.pinch(this);
});
// ...
return driver.pinch(el);
// ...
return el.pinch();
// zoom
function zoom(el) {
return Q.all([
this.getWindowSize(),
this.getLocation(el),
]).then(function(res) {
var size = res[0];
var loc = res[1];
var center = {
x: loc.x + size.width / 2,
y: loc.y + size.height / 2
};
var a1 = new wd.TouchAction(this);
a1.press({el: el}).moveTo({el: el, x: center.x, y: center.y - 100}).release();
var a2 = new wd.TouchAction(this);
a2.press({el: el}).moveTo({el: el, x: center.x, y: center.y + 100}).release();
var m = new wd.MultiAction(this);
m.add(a1, a2);
return m.perform();
}.bind(this));
};
wd.addPromiseChainMethod('zoom', zoom);
wd.addElementPromiseChainMethod('zoom', function() {
return this.browser.zoom(this);
});
// ...
return driver.zoom(el);
// ...
return el.zoom();
// Scroll to an element.
return driver.elementByName().then(function (el) {
driver.execute("mobile: scroll", [{direction: "down", element: el.value}]);
});
//Pulls a file from the device.
driver.pullFile("Library/AddressBook/AddressBook.sqlitedb")
.then(function (base64File) { /*...*/ })
// Pushes a file to the device.
driver.pushFile(path, data)
//SETTINGS
var settings = driver.settings();
browser.updateSettings({'someSetting': true});
12. wd.js在appium测试android的时候可以用哪些命令: 获取element
获取element有很多方式.
- 使用id查找,
driver.elementById("com.isen.trace.police:id/agree_use")
,这也是AI录制下来的代码的默认方式. - 支持xpath查找, 不过xpath实在是长:
let xpath = ' /hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.ScrollView/android.widget.LinearLayout/android.widget.Button[1]';
let el = await driver.elementByXPath(xpath);
- 支持按class查找
el = await driver.elementByClassName('android.widget.Button', cb)
可是,上面的方式都需要我使用工具AI或者UIAV查看才知道怎么选中element. 能不能只看app界面就知道怎么选中element呢? 那就是下面这个方式了.
- 支持使用android UIautomator api的UiSelectors. UiScrollable来查找元素.
怎么查找? 文档里里没说... google到appium论坛里面才知道方法,例如:
el = driver.elementByAndroidUIAutomator('new UiSelector().className(\"android.widget.Button\")',cb)
事实上就是把android命令直接作为字符串传入, android命令参考安卓的开发文档
那么看看能不能只知道element的文字(.text)就可以找到呢(假如文字可以唯一确定的话)? UiSelector文档是这样说的:
UiSelector().text(String text)
UiSelector().textContains(String text)
UiSelector().textMatches(String regex)
UiSelector().textStartsWith(String text)
假如一个控件,文字中包括"不同意"几个字, 可以这么写:
el = driver.elementByAndroidUIAutomator('new UiSelector().textContains("不同意")',cb)
13. wd.js在appium测试android的时候可以用哪些命令: 获取element的属性以用于测试期望值
//element可用的命令: element.xxxx()
element.getTagName(cb) -> cb(err, name)
element.clear(cb) -> cb(err) //清除input等输入区域的内容
element.isSelected(cb) -> cb(err, selected)
element.isEnabled(cb) -> cb(err, enabled)
element.isDisplayed(cb) -> cb(err, displayed)
element.getLocation(cb) -> cb(err, location)
element.getLocationInView(cb) -> cb(err, location)
element.getSize(cb) -> cb(err, size)
element.getOrientation(cb) -> cb(err, orientation)
element.tap(cb) -> cb(err)
element.click(cb) -> cb(err)
发送文本(不支持中文!)
element.setText("string", cb)
element.sendKeys("string", cb)
element.type("string", cb)
14. wd.js在appium测试android的时候可以用哪些命令: 虚拟按键
墙外: 安卓上所有按键的keycode在这儿
当然最好npm install -S keycode-for-android
, 这样就好用多了.
主要的几个按键:
back 4
menu 82
home 37
volume_up 24
volume_down 25
volume_mute 164
power 26
示例:
driver.pressKeycode(4,cb) //返回键
常见问题
1. Session断了怎么重连?
如果连接已经断开, 首先要知道sessionID:
var sid
var sessions = await driver.sessions()
sid = sessions[0].id
如果连接还没有断开,可以显摆sessionId存下来:
sid = await driver.sessionId()
然后通过attach连接ID
await driver.attach(sid)
也有detach()断开连接.
2. 软键盘上的Search按钮无法用KEYCODE_SEARCH或者KEYCODE_ENTER触发?
appium git 论坛上有人提出了这个问题, 解决方式是运行:
await driver.execute( "mobile: performEditorAction", { "action": "search" } )
3. 如何选择automationName?
Android5.0以上支持 UiAutomator2, 以下支持UiAutomator1
4. 使用UIAV 截图,遇到XML解析错误怎么办?UIautomator viewer org.xml.sax.SAXParseException;
- 关掉Appium Inspector和Server.
- 重启模拟器.
5. 如何使用图片搜索?
很遗憾截止目前wd.js不支持, 只有Python和ruby支持. python下安装Appium-Python-Client
pip install Appium-Python-Client