【问题标题】:Jenkins Emulator Plugin - Assigning Port ManuallyJenkins 模拟器插件 - 手动分配端口
【发布时间】:2021-04-26 08:17:20
【问题描述】:

最终更新 - 解决方案 - 连接到正确端口后安装失败,因为安装leaked file descriptors。按照here 中的建议更新环境变量可以解决问题

更新2 似乎环境变量会更改 gradle 命令的目标端口,但不会更改模拟器插件本身的等待循环。我决定手动启动模拟器

/var/lib/jenkins/android-sdk/emulator/emulator -avd testing24xlarge2 -wipe-data -no-window -no-audio  -partition-size 4096 -ports 5558,5559&
EMULATOR_PID=$!

在这里我意识到,我没有指定 adb 超时,所以我决定使用插件之前使用的 tcp 端口并重试,但这一点帮助都没有。

/var/lib/jenkins/android-sdk/emulator/emulator -report-console tcp:5829,max=96000 -avd testing24xlarge2 -wipe-data -no-window -no-audio  -partition-size 4096 -ports 5558,5559&
EMULATOR_PID=$!

。我能想到的一个可能但不太可能的原因是调试 apk 太大(我尝试的应用程序从 200 Mb 到 700 mb 不等)可能会导致此问题,但错误消息似乎并未表明这一点。尝试使用 adb 命令而不是 gradle 任务安装应用程序也没有帮助

android {
        adbOptions {
            timeOutInMs 6000000 // set timeout to 100 minutes
        }
    }
./gradlew assembleStagingDebug --no-daemon -Dkotlin.compiler.execution.strategy="in-process"
./gradlew assembleStagingDebugAndroidTest --no-daemon -Dkotlin.compiler.execution.strategy="in-process"
/var/lib/jenkins/android-sdk/platform-tools/adb -s emulator-5558 shell input keyevent 82
/var/lib/jenkins/android-sdk/platform-tools/adb -s emulator-5558 install -r -t  myapp/build/outputs/apk/staging/debug/myapp-staging-debug.apk
/var/lib/jenkins/android-sdk/platform-tools/adb -s emulator-5558 install -r -t  myapp/build/outputs/apk/androidTest/staging/debug/myapp-staging-debug-androidTest.apk
#/var/lib/jenkins/android-sdk/platform-tools/adb -e shell am instrument -w mypackage.testcases.tests/androidx.test.runner.AndroidJUnitRunner

在我尝试使用“可接受的 apk 大小”后,我会再次更新这篇文章


更新:我认为我已经正确识别了问题,但我仍然无法解决问题。

Ddmlib 会查找 5555,5586 之间的端口,当模拟器位于不同的端口时,应用程序安装自然会失败。 In official docs 建议我们可以利用环境变量让模拟器插件在我们想要的端口中搜索设备。但是与端口相关的环境变量(ANDROID_SERIAL, ANDROID_AVD_DEVICE 等)(我在我的主 Jenkins 配置中设置)都没有改变 adb -s 的目标。因此,使用ports 5558,5559 手动更改端口模拟器会失败,因为模拟器在端口 5558 中启动,但是

/var/lib/jenkins/android-sdk/platform-tools/adb -s emulator-5776 wait-for-device shell getprop dev.bootcomplete

在模拟器插件的随机分配端口中运行,当模拟器在我选择的端口中启动时卡住了。

_______________________________________________________________________________

在解决了数十个不同的问题以在模拟器中打开和运行 UI 测试后,我希望我被困在最后一个问题上,我尝试了所有我能想到的方法,但没有成功。

环境:我在 Min SDK = 24 的应用中使用 API 级别为 24 的模拟器以避免 INCOMPATIBLE_DEVICE_ERROR。 Jenkins 在 Ubuntu 20.04 中运行,但我认为这并不重要。我的目标 sdk 和编译 sdk 是 28(我也会尝试降级它们,但由于我已经解决了 INCOMPATIBLE 错误,我怀疑这会解决问题)。 Adb timeout 是 96000 秒,startup delay 是 20 秒。

正如下面的脚本将演示的那样,我很确定,我可以通过 adb 命令找到连接的模拟器,但是在安装和运行测试时,我尝试了两种不同的解决方案,但我都卡住了。

第一次解决方案尝试

  while [ "`/var/lib/jenkins/android-sdk/platform-tools/adb shell getprop service.bootanim.exit | tr -d '\r' `" != "1" ] ; do sleep 1; done
 /var/lib/jenkins/android-sdk/platform-tools/adb devices -l
/var/lib/jenkins/android-sdk/platform-tools/adb shell input keyevent 82
./gradlew  myapp:connectedStagingDebugAndroidTest --no-daemon -Dkotlin.compiler.execution.strategy="in-process"

它正确地等待设备启动(android 模拟器插件也在此之前检查 sys.boot_completed)并列出连接的设备 /passes the input key event 82

这会导致以下错误

om.android.build.gradle.internal.testing.ConnectedDevice > runTests[testing24xlarge2(AVD) - 7.0] [31mFAILED [0m
    com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException
        at com.android.build.gradle.internal.testing.ConnectedDevice.installPackage(ConnectedDevice.java:132)
[no message defined]
java.util.concurrent.ExecutionException: java.lang.RuntimeException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException
    at java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
    at com.android.ide.common.workers.ExecutorServiceAdapter.await(ExecutorServiceAdapter.kt:102)
    at com.android.build.gradle.internal.testing.BaseTestRunner.runTests(BaseTestRunner.java:201)
    at com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask.lambda$doTaskAction$2(DeviceProviderInstrumentTestTask.java:201)
    at com.android.builder.testing.api.DeviceProvider.use(DeviceProvider.java:53)
    at com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask.doTaskAction(DeviceProviderInstrumentTestTask.java:191)
    at 
Caused by: java.lang.RuntimeException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException
    at com.android.build.gradle.internal.testing.SimpleTestRunnable.run(SimpleTestRunnable.java:231)
Caused by: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException
    at com.android.build.gradle.internal.testing.ConnectedDevice.installPackage(ConnectedDevice.java:132)
    at com.android.build.gradle.internal.testing.SimpleTestRunnable.run(SimpleTestRunnable.java:134)
    ... 116 more
Caused by: com.android.ddmlib.InstallException
    at com.android.ddmlib.Device.installRemotePackage(Device.java:1174)
    at com.android.ddmlib.Device.installPackage(Device.java:998)
    at com.android.ddmlib.Device.installPackage(Device.java:974)
    at com.android.ddmlib.Device.installPackage(Device.java:963)
    at com.android.build.gradle.internal.testing.ConnectedDevice.installPackage(ConnectedDevice.java:126)
    ... 117 more
Caused by: com.android.ddmlib.ShellCommandUnresponsiveException
    at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:553)
    at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:378)
    at com.android.ddmlib.Device.executeShellCommand(Device.java:675)
    at com.android.ddmlib.Device.installRemotePackage(Device.java:1165)
    ... 121 more

(我试图在不限制重要信息的情况下尽可能多地削减异常链)

这里可以看到模拟器已附加

+ /var/lib/jenkins/android-sdk/platform-tools/adb devices -l
List of devices attached
emulator-5802          device product:sdk_google_phone_armv7 model:sdk_google_phone_armv7 device:generic transport_id:1

第二次解决方案尝试建议here here 也不起作用

./gradlew clean
./gradlew assembleDebug
./gradlew assembleDebugAndroidTest
/var/lib/jenkins/android-sdk/platform-tools/adb install app/build/outputs/apk/app-debug.apk
/var/lib/jenkins/android-sdk/platform-tools/adb install app/build/outputs/apk/app-debug-androidTest-unaligned.apk
/var/lib/jenkins/android-sdk/platform-tools/adbshell am instrument -w com.google.samples.apps.topeka.test/android.support.test.runner.AndroidJUnitRunner

这里的问题是之后

 /var/lib/jenkins/android-sdk/platform-tools/adb shell input keyevent 82
/var/lib/jenkins/android-sdk/platform-tools/adb install -r -t -g myapp/build/outputs/apk/staging/debug/myapp-staging-debug.apk //I have also tried adb -e to target the emulator as it is the only running device

控制台输出只是在安装命令处冻结(带有标志和不带标志 -r -t -g),并且您可能猜到下一个命令不会被执行。等了很长时间后,我收到以下错误,说 adb 可能无法工作,因为端口模拟器在。

adb: failed to install myapp/build/outputs/apk/staging/debug/myapp-staging-debug.apk: Performing Streamed Install
Build step 'Execute shell' marked build as failure
[android] Stopping Android emulator
emulator: WARNING: encryption is off
emulator: feeding guest with passive gps data, in headless mode
emulator: WARNING: Requested adb port (5775) is outside the recommended range [5555,5586]. ADB may not function properly for the emulator. See -help-port for details.
saving arm snapshot.... !!!

这是否因为端口错误而失败?如何在 Emulator Plugin 中指定我想要的端口号?它只让我

分配唯一的 TCP 端口以避免冲突。如果我在模拟器选项中指定它,它仍然会尝试使用它分配的随机端口执行 adb 命令,所以这不起作用。接下来我尝试复制我在控制台中看到的脚本来自己启动模拟器,但它似乎也不起作用(当我手动添加命令时模拟器没有启动

    /var/lib/jenkins/android-sdk/platform-tools/adb start-server
     /var/lib/jenkins/android-sdk/emulator/emulator -report-console tcp:5845,max=96000 -avd testing24xlarge2 -wipe-data -no-window -partition-size 4096 -ports 5558,5559
 while [ "`/var/lib/jenkins/android-sdk/platform-tools/adb shell getprop service.bootanim.exit | tr -d '\r' `" != "1" ] ; do sleep 1; done //Doesn't pass here

我完全被困在这里并且可能失去了我的大部分头发,第一次解决方案尝试的修复或第二次解决方案尝试都是可以接受的。

【问题讨论】:

    标签: android jenkins android-emulator adb avd


    【解决方案1】:

    可以通过环境变量来控制行为,例如:

    export ANDROID_SERIAL=emulator-5802
    

    还有一些,ADB_LOCAL_TRANSPORT_MAX_PORT 可能有用:

     $ADB_TRACE
         comma-separated list of debug info to log:
         all,adb,sockets,packets,rwx,usb,sync,sysdeps,transport,jdwp
     $ADB_VENDOR_KEYS         colon-separated list of keys (files or directories)
     $ANDROID_SERIAL          serial number to connect to (see -s)
     $ANDROID_LOG_TAGS        tags to be used by logcat (see logcat --help)
     $ADB_LOCAL_TRANSPORT_MAX_PORT max emulator scan port (default 5585, 16 emus)
     $ADB_MDNS_AUTO_CONNECT   comma-separated list of mdns services to allow auto-connect (default adb-tls-connect)
    

    通常也可以知道使用哪个端口:

     usb                      restart adbd listening on USB
     tcpip PORT               restart adbd listening on TCP on PORT
    

    【讨论】:

    • 感谢您提供信息丰富的答案,但我认为我在这里严重遗漏了一些东西。在仪表板/管理 Jenkins/配置系统中设置此变量不会影响正在查看的等待循环目标端口插件。接下来我假设这个变量只影响构建步骤并使用环境脚本插件注入 env 变量,但它也没有工作。我可能做错了什么,但对我来说,正如我在问题中所说,env 变量似乎不会影响行为。我还设置了 50 秒的启动延迟以确保变量被注入
    • @Prethia 您正在使用启动延迟提示做错了;可能while 循环。而且您需要为用户jenkins 设置环境...通常没有登录shell。模拟器也需要切换到无头,因为可能没有显示。
    • 问题似乎不是设置环境变量,我还从终端更改了环境变量作为詹金斯用户并在执行作业时打印它们。在我看来,插件本身并不尊重它承诺使用的环境变量。 github.com/jenkinsci/android-emulator-plugin/pull/55 似乎也表明了这一点。您之前是否使用过此功能,或者您是否根据文档回答?我很抱歉扩展了这个讨论,但我试图确定插件是否有问题。因为如果 ddmlib 失败,它就失去了它的目的
    • 如果我无法更改端口号(ddms 扫描到 5585 并查看 github.com/jenkinsci/android-emulator-plugin/blob/master/src/…),Ddmslib 失败总是会出现这种情况。正如您最初建议的那样,接下来我将尝试将 ADB_LOCAL_TRANSPORT_MAX_PORT 切换到类似 5900 的值。它保持最小传输端口相同并增加可能的鸸鹋数量,对吗?
    【解决方案2】:

    您遇到了允许 ddmlib 与 ADB 服务器通信的底层 TCP 套接字故障。为了对您进行调查,我建议您做两件事:

    1. 发生故障时,检查套接字状态“lsof -i 5037”
    2. 为了调查哪个请求实际失败,请运行 tcpdump/Wireshark。请记住,使用的接口很可能是环回。这样,您将看到执行的最后一个请求。从堆栈跟踪来看,这是 apk 推送到设备后的“pm install”

    【讨论】:

      猜你喜欢
      • 2020-07-13
      • 1970-01-01
      • 1970-01-01
      • 2014-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多