Docker for Mac을 사용하여 여러 Android 터미널과 병렬로 ADB를 사용하여 작업 수행

15777 단어 AndroidDockeradb
자기가 쓴 쪽지.
Docker for Mac으로 컨테이너에서 호스트 옆으로 연결된 Android 장치adb 방법
https://qiita.com/YusukeIwaki/items/5d31c10bc9bfe6d62845
Docker 컨테이너 두 개에서 터미널 두 개까지 ADB 연결을 하는 것을 조금 발전시키고 싶습니다.

-s 옵션과 유사한 환경 변수 ANDROID_SERIAL


일반적으로 여러 터미널을 PC에 삽입하는 경우 adb -s E32094823 shell 처럼 장치 직렬 ID를 -s로 많이 지정합니다.Docker로 이걸 하고 싶은데 가능하면 환경 변수로 하고 싶어요.
$ adb
Android Debug Bridge version 1.0.41
Version 29.0.1-5644136
Installed as /Users/yusuke-iwaki/Library/Android/sdk/platform-tools/adb

global options:
 -a         listen on all network interfaces, not just localhost
 -d         use USB device (error if multiple devices connected)
 -e         use TCP/IP device (error if multiple TCP/IP devices available)
 -s SERIAL  use device with given serial (overrides $ANDROID_SERIAL)
 -t ID      use device with given transport id
 -H         name of adb server host [default=localhost]
 -P         port of adb server [default=5037]
 -L SOCKET  listen on given socket for adb server [default=tcp:localhost:5037]
-s SERIAL use device with given serial (overrides $ANDROID_SERIAL)오!?
ANDROID_SERIAL?
android.googlesource.com/platform/system/core/+/master/adb/client/commandline.cpp
    // If none of -d, -e, or -s were specified, try $ANDROID_SERIAL.
    if (transport_type == kTransportAny && serial == nullptr) {
        serial = getenv("ANDROID_SERIAL");
    }
만약 -s에 아무것도 지정되지 않았다면 getenv("ANDROID_SERIAL")로 대입했기 때문에 -s와 같은 효과가 있었다.

docker-compose에서


docker-compose.yml
version: "3"
services:
  workspace_hogeperia:
    image: your_own/adb
    command: adb logcat
    environment:
      - ANDROID_SERIAL=CB1A2B3C45

  workspace_fugafone:
    image: your_own/adb
    command: adb logcat
    environment:
      - ANDROID_SERIAL=X51223098765
이런 느낌으로 환경 변수로 나누면 docker-compose up
workspace_fugafone_1   | 07-19 16:27:44.972  1455  2348 E ActivityManager:     at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:240)
workspace_fugafone_1   | 07-19 16:27:44.972  1455  2348 E ActivityManager:     at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3026)
workspace_fugafone_1   | 07-19 16:27:44.972  1455  2348 E ActivityManager:     at android.os.Binder.execTransact(Binder.java:674)
workspace_fugafone_1   | 07-19 16:27:44.989  1455  7369 E ActivityManager: Sending non-protected broadcast jp.co.sharp.android.keyguard.action.LOCKSCREEN_TOUCH_EVENT from system 1728:com.android.systemui/u0a48 pkg com.android.systemui
workspace_fugafone_1   | 07-19 16:27:44.989  1455  7369 E ActivityManager: java.lang.Throwable
workspace_fugafone_1   | 07-19 16:27:44.989  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.checkBroadcastFromSystem(ActivityManagerService.java:19258)
workspace_fugafone_1   | 07-19 16:27:44.989  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:19863)
workspace_fugafone_1   | 07-19 16:27:44.989  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:20005)
workspace_fugafone_1   | 07-19 16:27:44.989  1455  7369 E ActivityManager:     at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:240)
workspace_fugafone_1   | 07-19 16:27:44.989  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3026)
workspace_fugafone_1   | 07-19 16:27:44.989  1455  7369 E ActivityManager:     at android.os.Binder.execTransact(Binder.java:674)
workspace_hogeperia_1  | 08-21 16:42:57.992   652   841 E PPDaemon: void ScreenRefresher::ProcessRefreshWork(): pthread_cond_timedwait failed. err: Success
workspace_hogeperia_1  | 08-21 16:42:57.993   652   841 E PPDaemon: void ScreenRefresher::ProcessRefreshWork(): pthread_cond_timedwait failed. err: Success
workspace_hogeperia_1  | 08-21 16:42:57.995   652   841 E PPDaemon: void ScreenRefresher::ProcessRefreshWork(): pthread_cond_timedwait failed. err: Success
workspace_hogeperia_1  | 08-21 16:42:57.996   652   841 E PPDaemon: void ScreenRefresher::ProcessRefreshWork(): pthread_cond_timedwait failed. err: Success
workspace_hogeperia_1  | 08-21 16:42:57.999   652   841 E PPDaemon: void ScreenRefresher::ProcessRefreshWork(): pthread_cond_timedwait failed. err: Success
workspace_hogeperia_1  | 08-21 16:42:58.027  7445  7496 W [Photo Analyzer]: face provider: storage is not granted.
workspace_hogeperia_1  | 08-21 16:42:58.034 32045 32060 E DatabaseUtils: Writing exception to parcel
workspace_hogeperia_1  | 08-21 16:42:58.034 32045 32060 E DatabaseUtils: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/extended_images/media from pid=7445, uid=10085 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
workspace_hogeperia_1  | 08-21 16:42:58.034 32045 32060 E DatabaseUtils:   at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:608)
workspace_hogeperia_1  | 08-21 16:42:58.034 32045 32060 E DatabaseUtils:   at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:483)
workspace_hogeperia_1  | 08-21 16:42:58.034 32045 32060 E DatabaseUtils:   at android.content.ContentProvider$Transport.query(ContentProvider.java:212)
workspace_hogeperia_1  | 08-21 16:42:58.034 32045 32060 E DatabaseUtils:   at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:118)
workspace_hogeperia_1  | 08-21 16:42:58.034 32045 32060 E DatabaseUtils:   at android.os.Binder.execTransact(Binder.java:565)
workspace_hogeperia_1  | 08-21 16:42:58.038  7445  7496 W [Photo Analyzer]: [MessageHandlerThread]processFaceRecognition() please check permission:Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/extended_images/media from pid=7445, uid=10085 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission()
workspace_fugafone_1   | 07-19 16:27:45.022  1455  7369 I chatty  : uid=1000(system) Binder:1455_16 identical 2 lines
workspace_fugafone_1   | 07-19 16:27:45.037  1455  7369 E ActivityManager: Sending non-protected broadcast jp.co.sharp.android.keyguard.action.LOCKSCREEN_TOUCH_EVENT from system 1728:com.android.systemui/u0a48 pkg com.android.systemui
workspace_fugafone_1   | 07-19 16:27:45.037  1455  7369 E ActivityManager: java.lang.Throwable
workspace_fugafone_1   | 07-19 16:27:45.037  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.checkBroadcastFromSystem(ActivityManagerService.java:19258)
workspace_fugafone_1   | 07-19 16:27:45.037  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:19863)
workspace_fugafone_1   | 07-19 16:27:45.037  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:20005)
workspace_fugafone_1   | 07-19 16:27:45.037  1455  7369 E ActivityManager:     at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:240)
workspace_fugafone_1   | 07-19 16:27:45.037  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3026)
workspace_fugafone_1   | 07-19 16:27:45.037  1455  7369 E ActivityManager:     at android.os.Binder.execTransact(Binder.java:674)
workspace_fugafone_1   | 07-19 16:27:45.043   530   582 I NfcNciHal: nci_hal_lp_timeout_cback ()
workspace_fugafone_1   | 07-19 16:27:45.043   530   582 I NfcNciHal: nfc_hal_dm_power_mode_execute () event = 2 p=0 sz=8 kw=0
workspace_fugafone_1   | 07-19 16:27:45.043   530   582 I NfcNciHal: nfc_hal_dm_set_nfc_wake () DEASSERT
workspace_fugafone_1   | 07-19 16:27:45.054  1455  7369 E ActivityManager: Sending non-protected broadcast jp.co.sharp.android.keyguard.action.LOCKSCREEN_TOUCH_EVENT from system 1728:com.android.systemui/u0a48 pkg com.android.systemui
workspace_fugafone_1   | 07-19 16:27:45.054  1455  7369 E ActivityManager: java.lang.Throwable
workspace_fugafone_1   | 07-19 16:27:45.054  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.checkBroadcastFromSystem(ActivityManagerService.java:19258)
workspace_fugafone_1   | 07-19 16:27:45.054  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:19863)
workspace_fugafone_1   | 07-19 16:27:45.054  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:20005)
workspace_fugafone_1   | 07-19 16:27:45.054  1455  7369 E ActivityManager:     at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:240)
workspace_fugafone_1   | 07-19 16:27:45.054  1455  7369 E ActivityManager:     at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3026)
workspace_fugafone_1   | 07-19 16:27:45.054  1455  7369 E ActivityManager:     at android.os.Binder.execTransact(Binder.java:674)
wo
두 용기 중 두 개adb logcat를 병행해서 실행할 수 있다.

그나저나 Appium은 용이 아니에요.


adb를 직접 사용하는 상황이라면 이해하기 쉽지만 Appium처럼 내부에서adb를 포장하는 라이브러리를 사용하는 경우에는 주의해야 한다.
  • appium이 내부 포장adb에서 무엇을 하기 때문에 ANDROID_Serial을 솔직하게 읽지 않았습니다.
  • desired cap의 udid 매개 변수에 환경 변수를 명확하게 추가한 ANDROID_SERIAL에 가입하여 이런 일을 할 필요가 있다
  • appium의 구조는 몰래 내부에서 실행adb forward하고 맥 측의 포트를 연결하여 안드로이드 장치 측의 서버에 명령을 전송하기 때문에 병행 동작을 위해 포트 번호를 틀리게 해야 한다
  • 용기마다 desired cap을 바꾸는 시스템포트 매개 변수
  •  
    내부에adbforward를 만들면 확실히 그렇게 생각한다는 말을 듣지만, 소스를 보기 전에는 눈치채지 못했다.
    appium/appium-espresso-driver|lib/driver.js
        // set up the modified espresso server etc
        this.initEspressoServer();
        // Further prepare the device by forwarding the espresso port
        logger.debug(`Forwarding Espresso Server port ${DEVICE_PORT} to ${this.opts.systemPort}`);
        await this.adb.forwardPort(this.opts.systemPort, DEVICE_PORT);
    
    appium/appium-uiautomator2-driver|lib/driver.js
        // set up the modified UiAutomator2 server etc
        await this.initUiAutomator2Server();
    
        // Further prepare the device by forwarding the UiAutomator2 port
        logger.debug(`Forwarding UiAutomator2 Server port ${DEVICE_PORT} to ${this.opts.systemPort}`);
        await this.adb.forwardPort(this.opts.systemPort, DEVICE_PORT);
    
    시스템 포트를 같은 시간 오류 로그로 설정
    Appium에 systemPort를 설치할 때 로그
    workspace_fugafone_1  | 05:31:15 appium.1  | [debug] [WD Proxy] Matched '/status' to command name 'getStatus'
    workspace_fugafone_1  | 05:31:15 appium.1  | [debug] [WD Proxy] Proxying [GET /status] to [GET http://docker.for.mac.localhost:8200/wd/hub/status] with no body
    workspace_fugafone_1  | 05:31:15 appium.1  | [WD Proxy] Got an unexpected response: {"errno":"ECONNREFUSED","code":"ECONNREFUSED","syscall":"connect","address":"192.168.65.2","port":8200}
    workspace_fugafone_1  | 05:31:16 appium.1  | [debug] [WD Proxy] Matched '/status' to command name 'getStatus'
    workspace_fugafone_1  | 05:31:16 appium.1  | [debug] [WD Proxy] Proxying [GET /status] to [GET http://docker.for.mac.localhost:8200/wd/hub/status] with no body
    workspace_fugafone_1  | 05:31:16 appium.1  | [WD Proxy] Got an unexpected response: {"errno":"ECONNREFUSED","code":"ECONNREFUSED","syscall":"connect","address":"192.168.65.2","port":8200}
    workspace_fugafone_1  | 05:31:17 appium.1  | [debug] [WD Proxy] Matched '/status' to command name 'getStatus'
    workspace_fugafone_1  | 05:31:17 appium.1  | [debug] [WD Proxy] Proxying [GET /status] to [GET http://docker.for.mac.localhost:8200/wd/hub/status] with no body
    workspace_fugafone_1  | 05:31:17 appium.1  | [WD Proxy] Got an unexpected response: {"errno":"ECONNREFUSED","code":"ECONNREFUSED","syscall":"connect","address":"192.168.65.2","port":8200}
    
    이런 느낌이라 가벼운 타구를 봐도 포트 쟁탈을 눈치채기 어렵다.

    좋은 웹페이지 즐겨찾기