改造appium-android-driver
這個driver是UIAutomator1的driver奶赠,負責(zé)UIAutomator1的服務(wù)啟動、停止药有、命令接收和執(zhí)行毅戈。
工程結(jié)構(gòu)
- appium-android-driver(NodeJS工程)
- bootstrap(Maven工程)
本身appium-android-driver是一個nodejs工程,它還套著一個bootstrap的maven工程愤惰,這個maven工程就是用來打包UIAutomator1的苇经,會再bootstrap/bin的目錄下構(gòu)建生成一個叫AppiumBootstrap.jar的供外層的NodeJS工程使用。代碼在appium-android-driver/lib/bootstrap.js
的start函數(shù)中
const rootDir = path.resolve(__dirname, '..', '..');
const startDetector = (s) => { return /Appium Socket Server Ready/.test(s); };
const bootstrapJar = path.resolve(rootDir, 'bootstrap', 'bin', 'AppiumBootstrap.jar');
await this.init();
await this.adb.forwardPort(this.systemPort, 4724);
this.process = await this.uiAutomator.start(
bootstrapJar, 'io.appium.android.bootstrap.Bootstrap',
startDetector, '-e', 'pkg', appPackage,
'-e', 'disableAndroidWatchers', disableAndroidWatchers,
'-e', 'acceptSslCerts', acceptSslCerts);
修改pom.xml宦言,編譯bootstrap扇单,輸出AppiumBootstrap.jar
bootstrap工程是一個maven工程,用idea直接open這個文件夾即可奠旺,找到pom.xml蜘澜,右鍵Maven->Reimport,我們會發(fā)現(xiàn)有兩個maven依賴無法導(dǎo)入响疚,報找不到對應(yīng)的jar包:
<dependency>
<groupId>android</groupId>
<artifactId>android</artifactId>
<version>4.4.2_r4</version>
</dependency>
<dependency>
<groupId>android.test.uiautomator</groupId>
<artifactId>uiautomator</artifactId>
<version>4.4.2_r4</version>
</dependency>
原因是默認(rèn)的倉庫是從https://repo.maven.appache.org/maven2中找的鄙信,而這個倉庫根本沒有這兩個庫。
后來我發(fā)現(xiàn)Boundless的倉庫http://repo.boundlessgeo.com/main/中是有的稽寒,在這個pom.xml中配置這個倉庫就可以下載了扮碧。
<project>
...
<repositories>
<repository>
<id>Boundless</id>
<url>http://repo.boundlessgeo.com/main/</url>
</repository>
</repositories>
</project>
依賴庫搞定后,cmd切換到bootstrap文件夾目錄下,執(zhí)行mvn clean package
構(gòu)建maven工程慎王,我們會發(fā)現(xiàn)蚓土,并沒有在bin目錄下生成AndroidBootstrap.jar,此時要修改pom.xml中的maven-jar-plugin
:
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<!--jar輸出目錄-->
<outputDirectory>./bin</outputDirectory>
<!--輸出的jar包名稱-->
<finalName>AppiumBootstrap</finalName>
</configuration>
</plugin>
重新執(zhí)行mvn clean package
赖淤,AppiumBootstrap.jar就完成了正常構(gòu)建蜀漆,也就是說UIAutomator1構(gòu)建好了。
自定義appium-android-driver咱旱,并發(fā)布
找到appium-android-driver/package.json确丢,修改name,比如修改為appium-android-driver2
吐限,然后順便修改下version鲜侥,然后再appium-android-driver根目錄下執(zhí)行
npm install # 重新安裝依賴
npm publish # 發(fā)布
npm publish
是發(fā)布nodejs包的命令着帽,需要你在npmjs.com上注冊自己的賬號帆吻,發(fā)布的時候需要驗證你的賬號。
自定義Appium
跟自定義appium-android-driver一樣些阅,我們找到package.json狐粱,修改name和version舀寓,比如分別是appium2和1.12.1-20190401a,順便我們修改一下lib/main.js中的一條語句肌蜻,以驗證我們的修改是否生效:
async function logStartupInfo (parser, args) {
let welcome = `Welcome to Appium2 v${APPIUM_VER}, modified by chengming`; // 我修改了此處
let appiumRev = await getGitRev();
if (appiumRev) {
welcome += ` (REV ${appiumRev})`;
}
logger.info(welcome);
let showArgs = getNonDefaultArgs(parser, args);
if (_.size(showArgs)) {
logNonDefaultArgsWarning(showArgs);
}
let deprecatedArgs = getDeprecatedArgs(parser, args);
if (_.size(deprecatedArgs)) {
logDeprecationWarning(deprecatedArgs);
}
if (!_.isEmpty(args.defaultCapabilities)) {
logDefaultCapabilitiesWarning(args.defaultCapabilities);
}
// TODO: bring back loglevel reporting below once logger is flushed out
// logger.info('Console LogLevel: ' + logger.transports.console.level);
// if (logger.transports.file) {
// logger.info('File LogLevel: ' + logger.transports.file.level);
// }
}
還有要在package.json
中互墓,找到dependencies,把我們的appium的UIAutomator1的依賴改為"appium-android-driver2":"latest"蒋搜,使我們自定義的appium能夠使用我們自定義的UIAutomator1 driver
同樣篡撵,重新構(gòu)建和發(fā)布:
npm install
npm publish
在npmjs.com網(wǎng)站中,我的項目下就會看到appium2的工程:
使用自定義的appium
安裝:
npm i -g appium2
啟動
appium
效果
TODO:驗證自定義appium-android-driver是否生效
這個要修改bootstrap的java代碼齿诞,在啟動server的時候加上你的日志即可驗證酸休,后續(xù)再補充吧。
補充:2019-04-02 17:20
糾正AppiumBootstrap.jar的打包方式
官方readme.md沒有說怎么打包這個jar包的事情祷杈,我按照如上述的打包方式生成的jar是不可用的斑司,格式不正確。jar中的內(nèi)容應(yīng)該是一個classes.dex文件但汞,而不是編譯好的classes宿刮。
我們需要先把class文件打包成dex,然后再把dex打包成jar私蕾,shell代碼如下:
dx --dex --output=./classes.dex target/classes
jar -cvf AppiumBootstrap.jar -C ./ ./classes.dex
你需要配置好android的環(huán)境變量僵缺,使你的dx能夠全局調(diào)用。
既然打包方式知道了踩叭,并且appium是要求在appium-android-driver/bootstrap/bin下有個AppiumBootstrap.jar的磕潮,那么我們?nèi)サ舸饲敖omaven-jar-plugin設(shè)置的configuration翠胰,重新編寫一個shell腳本bootstrap.sh:
#!/bin/sh
mvn clean package # 清理環(huán)境,編譯class文件
dx --dex --output=./target/classes.dex target/classes # 將class文件打包自脯,生成dex文件
jar -cvf bin/AppiumBootstrap.jar -C ./ ./target/classes.dex # 將dex文件打包之景,生成jar
測試AppiumBootstrap.jar
我們找到bootstrap工程中的io.appium.android.bootstrap.Bootstrap.java
,在testRunServer方法的第一句膏潮,添加一段注釋:
public class Bootstrap extends UiAutomatorTestCase {
public void testRunServer() {
Logger.info("這是我自定義的Bootstrap锻狗,成功啦...");
Find.params = getParams();
boolean disableAndroidWatchers = Boolean.parseBoolean(getParams().getString("disableAndroidWatchers"));
boolean acceptSSLCerts = Boolean.parseBoolean(getParams().getString("acceptSslCerts"));
SocketServer server;
try {
server = new SocketServer(4724);
server.listenForever(disableAndroidWatchers, acceptSSLCerts);
} catch (final SocketServerException e) {
Logger.error(e.getError());
System.exit(1);
}
}
}
電腦插上手機,執(zhí)行:
adb devices
輸出:
chengmingdeMacBook-Pro:bootstrap cmlanche$ adb devices
List of devices attached
cf02d869 device
確保你的手機是連上電腦的焕参。
保存轻纪,執(zhí)行bootstrap.sh,在bin目錄會打包好AppiumBootstrap.jar叠纷,我們把它push到手機:
adb push ./bin/AppiumBootstrap.jar /data/local/tmp/AppiumBootstrap.jar
完成后刻帚,我們啟動UIAutomator1的測試:
adb shell uiautomator runtest /data/local/tmp/AppiumBootstrap.jar -c io.appium.android.bootstrap.Bootstrap
自定義AppiumBootstrap至此流程已通,接下來就是自定義權(quán)限框處理讲岁,讓Appium自主識別權(quán)限框我擂。
—— by cmlanche.com