记一次解决Original error: UiAutomator quit before it successfully launched
【前言】
在使用Appium的时候,你可能会遇见各种各样问题,如果不能很快在网上搜索解决,请耐心查看和分析Appium的输出日志,因为不同的环境以及不同的目的都会有千奇百怪的问题,也许你遇见的问题网上就没有人碰见过。
【背景以及环境】
我的开发环境是windows10 + Appium1.4.16.1 + IDEA + 真机测试。
当前,我配置好了desiredCapabilities,代码如下:
1 // desiredCapabilities 2 capabilities = new DesiredCapabilities(); 3 capabilities.setCapability("automationName","Appium"); 4 capabilities.setCapability("platformName","Android"); 5 capabilities.setCapability("platformVersion","5.1"); 6 capabilities.setCapability("deviceName", DEVICE_UDID); 7 capabilities.setCapability("udid", DEVICE_UDID); 8 capabilities.setCapability("noSign", "true");
9 //getClassesDir()私有函数,得到当前项目编译后的根目录 10 capabilities.setCapability("app", getClassesDir()+"\\"+APP_PATH); 11 12 //使用aapt2来获取安装的apk的包名 13 //由于会打包,所以我先把这些工具拷贝到宿主操作系统的某处 14 Runtime runtime = Runtime.getRuntime();
15 //copyDirectoryFromJarToDisk(directoryPath)私有函数,将项目中的文件夹拷贝到磁盘上去 16 String toolPath = copyDirectoryFromJarToDisk("tool"); 17 String apkPath = copyDirectoryFromJarToDisk("apk"); 18 String command = toolPath+"/aapt2.exe d badging " 19 +apkPath+"/"+APP_PATH.split("/")[1];
//下面这段将aapt2 dump badging *.apk得到的apk信息导出到磁盘上的apkinfo.txt中去 20 if(System.getProperty("os.name").toLowerCase().startsWith("win")){ 21 command += " > "+toolPath+"/apkinfo.txt"; 22 } else { 23 command += " | "+toolPath+"/apkinfo.txt"; 24 } 25 runtime.exec(command);
// getApkInfo(infoName, apkInfoTxtPath)私有函数从apkinfo.txt文件中获取相应字段 26 capabilities.setCapability("appPackage",getApkInfo("package",toolPath)); 27 capabilities.setCapability("appActivity",getApkInfo("launchable-activity",toolPath));
简单说上面的主要工作是配置DesiredCapabilities,其中为了了解安装的apk的包名和启动Activity,我使用了aapt2工具,将结果导入到磁盘的某个txt文件中去。然后包名的信息就从这个文件中读。
【问题以及解决对策,解决对策在第5点】
运行,报错,控制台第一行出现
Exception in thread "main" org.openqa.selenium.SessionNotCreatedException: Unable to create a new remote session. Please check the server log for more details. Original error: A new session could not be created. (Original error: UiAutomator quit before it successfully launched) (WARNING: The server did not provide any stacktrace information)
上面的内容说的就是UiAutomator(sdk提供的一个工具)没有正常启动。后来经过搜索,发现问题千奇百怪的,解决方案也五花八门,但是都不管用。于是就自行分析查看日志。过程如下:
1、查看appium日志,发现最早出现问题的是
是说要从Bilibili.apk读取strings.json,但是string.json路径里面有null值,因此不成功。不过影响不大,程序可以继续执行。
2、继续往下看
这里应该是执行卸载命令了,不过命令 adb -s $ANDROID_SERIAL uninstall PACKAGE 是可以执行的,但是上面提示uninstall还需要一个参数。接着往下看
3、
这里应该是问题关键了,Appium在之前拷贝它的AppiumBootstrap.jar到Android机器的/data/local/tmp下,然后这里的第一句使用了 adb shell uiautomator runtest AppiumBootstrap.jar -c io.appium.android.bootstrap.Bootstrap -e pkg PACKAGE 的语句来执行拷贝进去的AppiumBoostrap.jar,我在cmd中执行该句,当我省略 PACKAGE 时,得到了和上面一样的错误。
4、
由此,我得知我传进去的包名是有问题的,再看上面的打印出来的包名,发现格式不对。然后我使用vscode查看打印出的apkinfo.txt文档,发现其编码为UTF-16 LE。但是我的执行环境是utf-8,所以得到的包名在utf-8下看起来是这样的:
可见,每个可见字符之间隔了一个 \u0000 ,由此解决方法也显而易见了。
5、编码格式的解决方法是,对从aapt2打印的结果文字,在读取或者使用的时候进行转码,将 utf-16 LE 转为 utf-8 。最简单的方式就是除去多余的 \u0000 字符。比如对从文件中读到的字符加上
StringReadFromAAPT = StringReadFromAAPT.replace("\u0000","");
【后记】
不管怎么说,遇到难题搜索无果时,耐心分析日志才能真正节约时间。