即使能够从 cmd 从 "adb devices" 获取 udid,Appium Server 也无法检测到已连接的设备

Appium Server not detect connected device even when able to grab the udid from "adb devices" from cmd

我正在根据移动设备的数量设置 AppiumDriver devices/emulators,在每个驱动程序的设置过程中,将为每个创建的驱动程序设置一个 appium 服务器。但是,当创建服务器并将 AppiumDriver 初始化为 Android 或 IOS 时,服务器会生成无法连接到设备的错误,即使它能够毫无问题地检索设备来自 cmd:"adb devices",并打印正确的 udid。有什么我遗漏或忘记包括的东西吗?

详情如下:

代码(我设置了 3 个不同的程序):

public class BaseTest {

protected AppiumDriver<MobileElement> driver;
protected WebDriverWait wait;

//Change to default mobile Layout classes for anything on the screen
public PageObject pageObject = null;

public AppiumDriverSetup createDrivers = new AppiumDriverSetup();



@BeforeClass(alwaysRun=true)
public void setupDrivers() throws IOException {
    createDrivers.makeList();
    for(AppiumDriver<MobileElement> driver : createDrivers.getActiveList()){
        this.driver = driver;
        TLDriverFactory.setTLDriver(driver);
        wait = new WebDriverWait(TLDriverFactory.getTLDriver(), 10);
    }
}

@Test
public void testActivation() {
    assertTrue(driver != null);
    pageObject = new PageObject(TLDriverFactory.getTLDriver());
    driver.get("www.google.com");
}



public class AppiumDriverSetup {

enum Devices {
    ANDROID, IOS;
}

public static int deviceNum = 0;

public AppiumDriver<MobileElement> driver;

private List<Object> newDevice = new ArrayList<Object>();

private static List<AppiumDriver<MobileElement>> activeList = Collections.synchronizedList(new ArrayList<AppiumDriver<MobileElement>>());

AppOrBrowser determinePlatType = new AppOrBrowser();

ActiveAppiumPorts activePorts = new ActiveAppiumPorts();

public void makeList () throws IOException {
    Runtime rt = Runtime.getRuntime();
    Process p = rt.exec("adb devices");

    BufferedReader output = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line ="";

    while ((line = output.readLine()) != null) {
        if(StringUtils.isEmpty(line) || line.startsWith("List of devices attached")) {
            continue;
        }
        System.out.println(line);
        String [] serialNum = line.replace(" ", "").split("device");
        newDevice.add(Devices.ANDROID);
        newDevice.add(serialNum[0]);
        driver = setCaps((Devices)newDevice.get(0), (String)newDevice.get(1));
        activeList.add(driver);
    }

    //Implement the IOS Process
}

private AppiumDriver<MobileElement> setCaps(Devices d, String udid) throws MalformedURLException{
    AppiumDriver<MobileElement> driver = null;
    DesiredCapabilities cap = new DesiredCapabilities();

    String deviceName = "device"+ ++deviceNum;
    cap.setCapability(MobileCapabilityType.DEVICE_NAME, deviceName);
    if(d == Devices.ANDROID) {
        cap.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
    }
    if(d == Devices.IOS) {
        cap.setCapability(MobileCapabilityType.PLATFORM_NAME, "IOS");
    }
    cap.setCapability(MobileCapabilityType.UDID, udid);
    cap.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, "4000");
    cap.setCapability("noReset", false);

    //Help setup which browser or to run on an app.
    cap = determinePlatType.determinePlat(cap);

    //Generate AppiumPorts Class and retrieve generated port number.
    activePorts.generateServer();
    System.out.println("Argument to driver object : " + activePorts.getAppiumURL());
    switch (d) {
        case ANDROID: 
            driver = new AndroidDriver<MobileElement>(new URL(activePorts.getAppiumURL()), cap);
            break;
        case IOS:
            driver = new IOSDriver<MobileElement>(new URL(activePorts.getAppiumURL()), cap);
            break;
    }


    return driver;
}

public List<AppiumDriver<MobileElement>> getActiveList(){
    return activeList;
}

public void tearDown() {
    driver.quit();
}

}



public class ActiveAppiumPorts {

private int portNum = 0;

private String appiumPort = "500" + portNum;
private String serverIp = "127.0.0.1";

public String getAppiumURL() {
    String serverURL = "http://" + serverIp + ":" + appiumPort + "/wd/hub";
    portNum++;
    return serverURL;
}

public void generateServer() {
    Runtime runtime = Runtime.getRuntime();
    try {
        runtime.exec("cmd.exe /c start cmd.exe /k \"appium -a " + serverIp + " -p " + appiumPort + 
                "--session-override -dc \" {\"\"noReset\"\": \"\"false\"\"}\"\"");
        Thread.sleep(10000);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException r) {
        r.printStackTrace();
    }

}

public void stopServer() {
    Runtime runtime = Runtime.getRuntime();
    try {
        runtime.exec("taskkill /F /IM node.exe");
        runtime.exec("taskkill /F /IM cmd.exe");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

Appium 服务器日志:

[Appium] Welcome to Appium v1.8.1
[Appium] Non-default server args:
[Appium]   address: 127.0.0.1
[Appium]   port: 5000
[Appium]   defaultCapabilities: {
[Appium]     noReset: false
[Appium]   }
[Appium] Default capabilities, which will be added to each request unless overridden by desired capabilities:
[Appium]   noReset: false
[Appium] Appium REST http interface listener started on 127.0.0.1:5000
[HTTP] --> POST /wd/hub/session
[HTTP] {"desiredCapabilities":{"browserName":"Chrome","deviceName":"device1","newCommandTimeout":"4000","noReset":false,"platformName":"Android","udid":"192.168.174.102:5555\t"},"capabilities":{"desiredCapabilities":{"browserName":"Chrome","deviceName":"device1","newCommandTimeout":"4000","noReset":false,"platformName":"Android","udid":"192.168.174.102:5555\t"},"firstMatch":[{"browserName":"Chrome","platformName":"android"}]}}
[debug] [MJSONWP] Calling AppiumDriver.createSession() with args: [{"browserName":"Chrome","deviceName":"device1","newCommandTimeout":"4000","noReset":false,"platformName":"Android","udid":"192.168.174.102:5555\t"},null,{"desiredCapabilities":{"browserName":"Chrome","deviceName":"device1","newCommandTimeout":"4000","noReset":false,"platformName":"Android","udid":"192.168.174.102:5555\t"},"firstMatch":[{"browserName":"Chrome","platformName":"android"}]}]
[debug] [BaseDriver] Event 'newSessionRequested' logged at 1534263446888 (09:17:26 GMT-0700 (Pacific Daylight Time))
[BaseDriver] The capabilities ["noReset"] are not standard capabilities and should have an extension prefix
[BaseDriver] Boolean capability passed in as string. Functionality may be compromised.
[Appium] Could not parse W3C capabilities: 'deviceName' can't be blank. Falling back to JSONWP protocol.
[Appium] The following capabilities were provided in the JSONWP desired capabilities that are missing in W3C capabilities: ["noReset","browserName","deviceName","newCommandTimeout","platformName","udid"]. Falling back to JSONWP protocol.
[Appium] Creating new AndroidDriver (v2.7.0) session
[Appium] Capabilities:
[Appium]   noReset: false
[Appium]   browserName: Chrome
[Appium]   deviceName: device1
[Appium]   newCommandTimeout: 4000
[Appium]   platformName: Android
[Appium]   udid: 192.168.174.102:5555
[debug] [BaseDriver] Creating session with MJSONWP desired capabilities: {"noReset":false,"browserNa...
[BaseDriver] Capability 'newCommandTimeout' changed from string ('4000') to integer (4000). This may cause unexpected behavior
[BaseDriver] Session created with session id: 9beb9dd1-e6c3-4fa2-9cd6-7fb55d4a820b
[debug] [AndroidDriver] Getting Java version
[AndroidDriver] Java version is: 1.8.0_171
[AndroidDriver] We're going to run a Chrome-based session
[AndroidDriver] Chrome-type package and activity are com.android.chrome and com.google.android.apps.chrome.Main
[ADB] Checking whether adb is present
[ADB] Found 3 'build-tools' folders under 'C:\Users\<username>\AppData\Local\Android\Sdk' (newest first):
[ADB]     C:/Users/<username>/AppData/Local/Android/Sdk/build-tools/28.0.0-rc1
[ADB]     C:/Users/<username>/AppData/Local/Android/Sdk/build-tools/27.0.3
[ADB]     C:/Users/<username>/AppData/Local/Android/Sdk/build-tools/26.0.2
[ADB] Using adb.exe from C:\Users\<username>\AppData\Local\Android\Sdk\platform-tools\adb.exe
[AndroidDriver] Retrieving device list
[debug] [ADB] Trying to find a connected android device
[debug] [ADB] Getting connected devices...
[debug] [ADB] 2 device(s) connected
[AndroidDriver] Error: Device 192.168.174.102:5555       was not in the list of connected devices
[AndroidDriver]     at Object.wrappedLogger.errorAndThrow (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\appium-support\lib\logging.js:78:13)
[AndroidDriver]     at Object.callee[=12=][=12=]$ (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\appium-android-driver\lib\android-helpers.js:161:16)
[AndroidDriver]     at tryCatch (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\babel-runtime\regenerator\runtime.js:67:40)
[AndroidDriver]     at GeneratorFunctionPrototype.invoke [as _invoke] (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\babel-runtime\regenerator\runtime.js:315:22)
[AndroidDriver]     at GeneratorFunctionPrototype.prototype.(anonymous function) [as next] (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\babel-runtime\regenerator\runtime.js:100:21)
[AndroidDriver]     at GeneratorFunctionPrototype.invoke (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\babel-runtime\regenerator\runtime.js:136:37)
[AndroidDriver]     at <anonymous>
[debug] [AndroidDriver] Shutting down Android driver
[debug] [AndroidDriver] Called deleteSession but bootstrap wasn't active
[debug] [BaseDriver] Event 'newSessionStarted' logged at 1534263447383 (09:17:27 GMT-0700 (Pacific Daylight Time))
[MJSONWP] Encountered internal error running command: Error: Device 192.168.174.102:5555         was not in the list of connected devices
[MJSONWP]     at Object.wrappedLogger.errorAndThrow (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\appium-support\lib\logging.js:78:13)
[MJSONWP]     at Object.callee[=12=][=12=]$ (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\appium-android-driver\lib\android-helpers.js:161:16)
[MJSONWP]     at tryCatch (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\babel-runtime\regenerator\runtime.js:67:40)
[MJSONWP]     at GeneratorFunctionPrototype.invoke [as _invoke] (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\babel-runtime\regenerator\runtime.js:315:22)
[MJSONWP]     at GeneratorFunctionPrototype.prototype.(anonymous function) [as next] (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\babel-runtime\regenerator\runtime.js:100:21)
[MJSONWP]     at GeneratorFunctionPrototype.invoke (C:\Users\<username>\AppData\Roaming\npm\node_modules\appium\node_modules\babel-runtime\regenerator\runtime.js:136:37)
[MJSONWP]     at <anonymous>
[HTTP] <-- POST /wd/hub/session 500 619 ms - 207

Mvn 日志:

 [INFO] Running TestSuite
  192.168.174.102:5555    device
  chrome
  Argument to driver object : http://127.0.0.1:5000/wd/hub
  [ERROR] Tests run: 2, Failures: 1, Errors: 0, Skipped: 1, Time elapsed: 
  12.489 s <<< FAILURE! - in TestSuite
  [ERROR] setupDrivers(BaseTest.BaseTest)  Time elapsed: 12.373 s  <<< 
  FAILURE!
  org.openqa.selenium.WebDriverException:
  An unknown server-side error occurred while processing the command. 
  Original error: Device 192.168.174.102:5555      was not in the list of 
  connected devices (WARNING: The server did not provide any stacktrace 
  information)
  Command duration or timeout: 718 milliseconds 
  Build info: version: '3.11.0', revision: 'e59cfb3', time: '2018-03- 
  11T20:26:55.152Z'
  System info: host: 'LAPTOP-L1BFDSGL', ip: '192.168.174.2', os.name: 
  'Windows 10', os.arch: 'x86', os.version: '10.0', java.version: 
  '1.8.0_181'
  Driver info: driver.version: AndroidDriver
            at BaseTest.BaseTest.setupDrivers(BaseTest.java:34)

TestNG 报告:

org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: Device 192.168.174.102:5555  was not in the list of connected devices (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 718 milliseconds
Build info: version: '3.11.0', revision: 'e59cfb3', time: '2018-03-11T20:26:55.152Z'
System info: host: 'LAPTOP-L1BFDSGL', ip: '192.168.174.2', os.name: 'Windows 10', os.arch: 'x86', os.version: '10.0', java.version: '1.8.0_181'
Driver info: driver.version: AndroidDriver
    at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:214)
    at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:166)
    at org.openqa.selenium.remote.JsonWireProtocolResponse.lambda$new[=14=](JsonWireProtocolResponse.java:53)
    at org.openqa.selenium.remote.JsonWireProtocolResponse.lambda$getResponseFunction(JsonWireProtocolResponse.java:91)
    at org.openqa.selenium.remote.ProtocolHandshake.lambda$createSession[=14=](ProtocolHandshake.java:123)
    at java.util.stream.ReferencePipeline.accept(ReferencePipeline.java:193)
    at java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:958)
    at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
    at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)
    at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:126)
    at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:73)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:136)
    at io.appium.java_client.remote.AppiumCommandExecutor.execute(AppiumCommandExecutor.java:129)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:545)
    at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:42)
    at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1)
    at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1)
    at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:209)
    at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:132)
    at io.appium.java_client.DefaultGenericMobileDriver.<init>(DefaultGenericMobileDriver.java:38)
    at io.appium.java_client.AppiumDriver.<init>(AppiumDriver.java:84)
    at io.appium.java_client.AppiumDriver.<init>(AppiumDriver.java:94)
    at io.appium.java_client.android.AndroidDriver.<init>(AndroidDriver.java:80)
    at AppiumDriverSetUp_Lib.AppiumDriverSetup.setCaps(AppiumDriverSetup.java:87)
    at AppiumDriverSetUp_Lib.AppiumDriverSetup.makeList(AppiumDriverSetup.java:57)
    at BaseTest.BaseTest.setupDrivers(BaseTest.java:34)
... Removed 34 stack frames

导致该问题的原因是在将 udid 存储在 SerialNum[0] 中时添加的空 space。因此,当 Appium 服务器尝试连接到设备时,额外的 space 会成为阻碍。我使用 trim() 编辑了 udid String 值以删除任何额外的 space:

private AppiumDriver<MobileElement> setCaps(Devices d, String udid) throws MalformedURLException{
    AppiumDriver<MobileElement> driver = null;
    DesiredCapabilities cap = new DesiredCapabilities();

    String deviceName = "device"+ ++deviceNum;
    cap.setCapability(MobileCapabilityType.DEVICE_NAME, deviceName);
    if(d == Devices.ANDROID) {
        cap.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
    }
    if(d == Devices.IOS) {
        cap.setCapability(MobileCapabilityType.PLATFORM_NAME, "IOS");
    }
    cap.setCapability(MobileCapabilityType.UDID, udid.trim());
    cap.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, "4000");
    cap.setCapability("noReset", false);