我搭建了一个小环境尝试使用 appium 来自动运行我们的 APP,但是在环境搭建好之后使用 Appium 自带的 Contact Manager 这个小 APP 试运行了一次,全程通过,稍后切换成我们公司自己的 APP 来运行,然而 appium 启动时报错如下:

info: Welcome to Appium v1.3.4 (REV c8c79a85fbd6870cd6fc3d66d038a115ebe22efe)
info: Appium REST http interface listener started on 0.0.0.0:4723
info: Console LogLevel: debug
info: --> POST /wd/hub/session {"capabilities":{"desiredCapabilities":{"app":"D:
\\AppiumTest/apps/wcc9_0_0_17_20170109.apk","appPackage":"com.wochacha","appActi
vity":".StartupActivity","platformVersion":"4.4","browserName":"","platformName"
:"Android","udid":"127.0.0.1:6555","deviceName":"127.0.0.1:6555"},"requiredCapab
ilities":{}},"desiredCapabilities":{"app":"D:\\AppiumTest/apps/wcc9_0_0_17_20170
109.apk","appPackage":"com.wochacha","appActivity":".StartupActivity","platformV
ersion":"4.4","browserName":"","platformName":"Android","udid":"127.0.0.1:6555",
"deviceName":"127.0.0.1:6555"},"requiredCapabilities":{}}
info: Client User-Agent string: Apache-HttpClient/4.3.3 (java 1.5)
info: [debug] Using local app from desired caps: D:\AppiumTest\apps\wcc9_0_0_17_
20170109.apk
info: [debug] Creating new appium session 94e12953-dd11-41fa-b0b7-0010aa200644
info: Starting android appium
info: [debug] Getting Java version
info: Java version is: 1.8.0_05
info: [debug] Using fast reset? true
info: [debug] Preparing device for session
info: [debug] Checking whether app is actually present
info: [debug] Checking whether adb is present
info: [debug] Using adb from E:\Android-64-sdk\sdk\platform-tools\adb.exe
info: Retrieving device
info: [debug] Trying to find a connected android device
info: [debug] Getting connected devices...
info: [debug] executing cmd: E:\Android-64-sdk\sdk\platform-tools\adb.exe device
s
info: [debug] 1 device(s) connected
info: Found device 127.0.0.1:6555
info: [debug] Setting device id to 127.0.0.1:6555
info: [debug] Waiting for device to be ready and to respond to shell commands (t
imeout = 5)
info: [debug] executing cmd: E:\Android-64-sdk\sdk\platform-tools\adb.exe -s 127
.0.0.1:6555 wait-for-device
info: [debug] executing cmd: E:\Android-64-sdk\sdk\platform-tools\adb.exe -s 127
.0.0.1:6555 shell "echo 'ready'"
info: [debug] Starting logcat capture
info: [debug] Getting device API level
info: [debug] executing cmd: E:\Android-64-sdk\sdk\platform-tools\adb.exe -s 127
.0.0.1:6555 shell "getprop ro.build.version.sdk"
info: [debug] Device is at API Level 19
info: Device API level is: 19
info: [debug] executing cmd: E:\Android-64-sdk\sdk\platform-tools\adb.exe -s 127
.0.0.1:6555 shell "getprop persist.sys.language"
info: [debug] Current device persist.sys.language: zh_CN
info: [debug] java -jar "D:\nodejs\node_modules\appium\node_modules\appium-adb\j
ars\appium_apk_tools.jar" "stringsFromApk" "D:\AppiumTest\apps\wcc9_0_0_17_20170
109.apk" "C:\Users\ADMINI~1\AppData\Local\Temp\com.wochacha" zh_CN
info: [debug] No strings.xml for language 'zh_CN', getting default strings.xml
info: [debug] java -jar "D:\nodejs\node_modules\appium\node_modules\appium-adb\j
ars\appium_apk_tools.jar" "stringsFromApk" "D:\AppiumTest\apps\wcc9_0_0_17_20170
109.apk" "C:\Users\ADMINI~1\AppData\Local\Temp\com.wochacha"
info: [debug] executing cmd: E:\Android-64-sdk\sdk\platform-tools\adb.exe -s 127
.0.0.1:6555 push "C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\com.wochacha\\strin
gs.json" /data/local/tmp
info: [debug] Checking whether aapt is present
info: [debug] Using aapt from E:\Android-64-sdk\sdk\build-tools\android-4.4\aapt
.exe
info: [debug] Retrieving process from manifest.
info: [debug] executing cmd: E:\Android-64-sdk\sdk\build-tools\android-4.4\aapt.
exe dump xmltree D:\AppiumTest\apps\wcc9_0_0_17_20170109.apk AndroidManifest.xml

info: [debug] Set app process to: com.wochacha
info: [debug] Not uninstalling app since server not started with --full-reset
info: [debug] Checking app cert for D:\AppiumTest\apps\wcc9_0_0_17_20170109.apk.

info: [debug] executing cmd: java -jar D:\nodejs\node_modules\appium\node_module
s\appium-adb\jars\verify.jar D:\AppiumTest\apps\wcc9_0_0_17_20170109.apk
info: [debug] App not signed with debug cert.
info: [debug] Resigning apk.
info: [debug] executing cmd: java -jar D:\nodejs\node_modules\appium\node_module
s\appium-adb\jars\sign.jar D:\AppiumTest\apps\wcc9_0_0_17_20170109.apk --overrid
e
info: [debug] Stopping logcat capture
info: [debug] Logcat terminated with code null, signal SIGTERM
info: [debug] Sent shutdown command, waiting for UiAutomator to stop...
warn: UiAutomator did not shut down fast enough, calling it gone
info: [debug] Cleaning up android objects
info: [debug] Cleaning up appium session
error: Failed to start an Appium session, err was: Error: Command failed: Except
ion in thread "main" java.lang.RuntimeException: Unable to rename input apk. D:\
AppiumTest\apps\wcc9_0_0_17_20170109.apk
        at s.Sign.sign(Sign.java:421)
        at s.Sign.main(Sign.java:532)

info: [debug] Error: Command failed: Exception in thread "main" java.lang.Runtim
eException: Unable to rename input apk. D:\AppiumTest\apps\wcc9_0_0_17_20170109.
apk
        at s.Sign.sign(Sign.java:421)
        at s.Sign.main(Sign.java:532)

    at ChildProcess.exithandler (child_process.js:658:15)
    at ChildProcess.emit (events.js:98:17)
    at maybeClose (child_process.js:766:16)
    at Process.ChildProcess._handle.onexit (child_process.js:833:5)
info: [debug] Responding to client with error: {"status":33,"value":{"message":"
A new session could not be created. (Original error: Command failed: Exception i
n thread \"main\" java.lang.RuntimeException: Unable to rename input apk. D:\\Ap
piumTest\\apps\\wcc9_0_0_17_20170109.apk\r\n\tat s.Sign.sign(Sign.java:421)\r\n\
tat s.Sign.main(Sign.java:532)\r\n)","killed":false,"code":1,"signal":null,"orig
Value":"Command failed: Exception in thread \"main\" java.lang.RuntimeException:
 Unable to rename input apk. D:\\AppiumTest\\apps\\wcc9_0_0_17_20170109.apk\r\n\
tat s.Sign.sign(Sign.java:421)\r\n\tat s.Sign.main(Sign.java:532)\r\n"},"session
Id":null}
info: <-- POST /wd/hub/session 500 11260.402 ms - 602

appium 本身的脚本如下:

public AppiumTest(String app, String reset) throws IOException {
        this.appDir = System.getProperty("user.dir") + "/apps/" + app   + ".apk";
        this.packageName = (GetApkInfo.getApkInfoByFilePath(appDir).toString().split(",")[0]).split("=")[1];

        this.appName = app;
        this.resetable = reset;

        this.setDevices();
        this.setDrivers();
        this.setDriversTimeouts();
    }

    /**
     * 将所有已连接设
     * 
     * 备的id放到数组deviceId中
     * @throws IOException
     */
    public void setDevices() throws IOException {
        deviceId = new ArrayList<String>();
        int unknownIdDevicesNum = 0;
        int offlineDevicesNum = 0;
        int unauthorizedDevicesNum = 0;

        BufferedReader br = ExecCmd.execCmd("adb devices");
        String line = null;
        while ((line = br.readLine()) != null) {
            if (line.matches(".*offline$")) {
                offlineDevicesNum++;
            } else if (line.matches(".*unauthorized$")) {
                unauthorizedDevicesNum++;
            } else if (line.matches(".*0123456789ABCDEF.*")) {
                unknownIdDevicesNum++;
            } else if (line.matches(".*device$")) {
                String[] s = line.split("\t");
                deviceId.add(s[0]);
            }
        }
        if (unknownIdDevicesNum > 1) {
            assertTrue("2台或2台以上设备id同为0123456789ABCDEF,请保证最多只有一台", false);
        }
        if (offlineDevicesNum > 0) {
            assertTrue("1台或1台以上设备为离线状态,请检查", false);
        }
        if (unauthorizedDevicesNum > 0) {
            assertTrue("1台或1台以上设备为未授权状态,请检查", false);
        }
        if (deviceId.isEmpty()) {
            assertTrue("没有检测到设备,请检测设备连接是否正常", false);
        } else {
            deviceNum = deviceId.size();
        }
    }

    /**
     * 为所有连接上的设备创建各自的appiumdriver,并添加到appiumDrivers数组
     * @throws IOException
     */
    public void setDrivers() throws IOException {
        appiumDrivers = new AndroidDriver[deviceNum];
        for (int i = 0; i < deviceNum; i++) {
            appiumDrivers[i] = this.getDriver(i);
        }
    }
public AndroidDriver getDriver(int index) throws MalformedURLException {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability(CapabilityType.BROWSER_NAME, "");
        capabilities.setCapability("platformName", "Android");
        capabilities.setCapability("deviceName", deviceId.get(index));
        capabilities.setCapability("udid", deviceId.get(index)); // 设置device id
        capabilities.setCapability("platformVersion", "4.4");
        capabilities.setCapability("app", this.appDir);
        ExecCmd.execCmd("cmd.exe /k start appium --port " + (4723 + 2 * index)
                +" " + this.resetable +  " --command-timeout " + COMMAND_TIMEOUT); // 启动appium server


        // 等待10秒钟让appium server起来
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AndroidDriver(new URL("http://127.0.0.1:"
                + (4723 + 2 * index) + "/wd/hub"), capabilities);
    }

诚然遇见问题首先自己解决,发现跟 resetable 参数有关系,因为之后排查发现我无论是否穿 no-reset 值过去都会重新安装。之后长达一个星期的时间我在 apk 包的权限(类似混淆、签名、加密等等情况做了排除)

本身脚本的问题(尝试不在启动安装 apk 包)我将

ExecCmd.execCmd("cmd.exe /k start appium --port " + (4723 + 2 * index)
                +" " + this.resetable +  " --command-timeout " + COMMAND_TIMEOUT); // 启动appium server

修改成如下:

capabilities.setCapability("appPackage", "com.wochacha");
capabilities.setCapability("appActivity", ".StartupActivity");
ExecCmd.execCmd("cmd.exe /k start appium");

来尝试直接运行脚本,第一次可以运行,第二次就报同样的错误,求各位大神帮忙指点一下迷津。


↙↙↙阅读原文可查看相关链接,并与作者交流