Windows 11 içinde WSL Linux Sanal Makinesine Android Cihazını Bağlayarak Hata Ayıklamak

Cem Topkaya
7 min readDec 6, 2024

--

Amacım: Android telefonumdaki uygulamayı Appium ile test etmek istiyorum.

Ortamım: Windows 11 benim ev sahibi bilgisayarım (dizüstü makinenin işletim sistemi). İçinde Ubuntu 24 sanal makinesi WSL olarak çalışıyor. Docker konteyner olarak appium/appium kalıbını kullanarak bir geliştirme ortamı hazırladım.

Sorunum: Android telefonumu Win11 içinde adb devices komutunun çıktısında görüyorum ancak Ubuntu içinde listeleyemiyorum.

Çözümüm: Win11'in WSL’e USB bağlantılarını yönlendirmesi gerekiyor ve bunu usbipd-win 4.3.0 uygulamasıyla yapmak gerekiyor. Kaynak için buraya bakabilirsiniz.

Öncelikle WSL içinde adb işlemlerini yapabilmek için WSL içindeki Ubuntu sunucunuzda android komut satırı araçlarını kurun:

sudo apt update
sudo apt install android-tools-adb

Win11 içinde en başta telefonunuz “Not Shared” durumundadır. Ama telefonunuz “Attached” veya “Shared” durumlarından birinde de olabilir. Eğer telefonunuzu başlangıç durumu olan “Not Shared” durumuna getirmek istiyorsanız usbipd unbind --busid 4–4 komutunu çalıştırabiliriz.

Redmine ne Win11 ne Noble üzerine eklenmiş

Eğer Win11 makinenizde adb sunucusu çalışıyorsa kapandığından emin oluncaya kadar adb kill-server komutunu çalıştırabilirsiniz.

D:\adb-platform-tools>adb kill-server
cannot connect to daemon at tcp:5037: cannot connect to 127.0.0.1:5037: No connection could be made because the target machine actively refused it. (10061)

NOT: Bu kısımları daha açıklayıcı olsun diye sonradan tekrar yazıyorum. Bu yüzden bus id değeri 2–3 yerine 4–4 olarak tanınan telefonu işlediğim ekran görüntülerini paylaşacağım. Aynı telefon ancak farklı bus id değeri, korkulacak bir şey yok ;)

Hem W11 hem Noble üzerinde adb sunucusu çalışmıyor

adb kill-server

Windows 11 sisteminize yazılımı indirip kurduktan sonra usbipd list komutuyla bağlı cihazları listeleyin:

usbipd list

Önce Redmine telefonu Shared durumuna (STATE) getirelim

Administrator haklarıyla tekrar cihazı Shared durumuyla bağlamaya çalışıyorum:

usbipd attach --wsl --busid 4–4

Telefonu WSL’e Bağlamak

Android cihazın BUSID değerini usbipd attach --wsl --busid 4-4 komutuyla WSL sunucunuza bağlıyorsunuz:

usbipd attach --wsl --busid 4-4

Win11 içinde telefonunuzun STATE bilgisi artık Attached oldu:

usbipd list

Telefonu Konteynere Bağlamak

Appium’un konteyner kalıplarını docker hub üzerinden bulabilirsiniz ancak kendinize özgü bir konteyner kalıbı üretecekseniz bu adresteki Dockerfile işinize yarayacaktır.

Ben scrcpy ile konteyner içinden telefonun ekranına erişebilmek için Dockerfile dosyasını güncelledim. Bazı ağ araçlarını ekledim, python ile konteynerde geliştirme yapmak için pip ekledim vs. Önce repoyu çektim sonra Dockerfile dosyasını aşağıdaki gibi güncelledim:

git clone https://github.com/appium/appium-docker-android.git

Güncelleyelim Dockerfile dosyamızı:

FROM ubuntu:noble

ENV DEBIAN_FRONTEND=noninteractive

#==================
# General Packages
#------------------
# ca-certificates
# SSL client
# curl
# Transfer data from or to a server
# gnupg
# Encryption software. It is needed for nodejs
# libgconf-2-4
# Required package for chrome and chromedriver to run on Linux
# libqt5webkit5
# Web content engine (Fix issue in Android)
# openjdk-11-jdk
# Java
# sudo
# Sudo user
# tzdata
# Timezone
# unzip
# Unzip zip file
# wget
# Network downloader
# xvfb
# X virtual framebuffer
# zip
# Make a zip file
#==================
RUN apt update && apt dist-upgrade -y

RUN apt install -y \
ca-certificates \
curl \
gnupg \
sudo \
tzdata \
unzip \
wget \
xvfb \
zip \
libqt5webkit5 \
openjdk-11-jdk \
ffmpeg
# && rm -rf /var/lib/apt/lists/*

RUN apt install -y net-tools iproute2 \
maven \
git \
# ffmpeg libsdl2-2.0-0 adb gcc pkg-config meson ninja-build libavcodec-dev libavdevice-dev libavformat-dev libavutil-dev libswresample-dev libusb-1.0-0-dev \
python3-pip


#===============
# Set JAVA_HOME
#===============
ENV JAVA_HOME="/usr/lib/jvm/java-11-openjdk-amd64" \
PATH=$PATH:$JAVA_HOME/bin

#===============================
# Set Timezone (UTC as default)
#===============================
ENV TZ "UTC"
RUN echo "${TZ}" > /etc/timezone \
&& dpkg-reconfigure --frontend noninteractive tzdata

#===============
# Create a user
#===============
ARG USER_PASS=secret
RUN groupadd androidusr \
--gid 1301 \
&& useradd androidusr \
--uid 1300 \
--gid 1301 \
--create-home \
--shell /bin/bash \
&& usermod -aG sudo androidusr \
&& echo androidusr:${USER_PASS} | chpasswd \
&& echo 'androidusr ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers

WORKDIR /home/androidusr

#=====================
# Install Android SDK
#=====================
ENV SDK_VERSION=commandlinetools-linux-8512546_latest
ENV ANDROID_BUILD_TOOLS_VERSION=34.0.0
ENV ANDROID_FOLDER_NAME=cmdline-tools
ENV ANDROID_DOWNLOAD_PATH=/home/androidusr/${ANDROID_FOLDER_NAME} \
ANDROID_HOME=/opt/android \
ANDROID_TOOL_HOME=/opt/android/${ANDROID_FOLDER_NAME}

RUN wget -O tools.zip https://dl.google.com/android/repository/${SDK_VERSION}.zip && \
unzip tools.zip && rm tools.zip && \
chmod a+x -R ${ANDROID_DOWNLOAD_PATH} && \
chown -R 1300:1301 ${ANDROID_DOWNLOAD_PATH} && \
mkdir -p ${ANDROID_TOOL_HOME} && \
mv ${ANDROID_DOWNLOAD_PATH} ${ANDROID_TOOL_HOME}/tools
ENV PATH=$PATH:${ANDROID_TOOL_HOME}/tools:${ANDROID_TOOL_HOME}/tools/bin

# https://askubuntu.com/questions/885658/android-sdk-repositories-cfg-could-not-be-loaded
RUN mkdir -p ~/.android && \
touch ~/.android/repositories.cfg && \
echo y | sdkmanager "platform-tools" && \
echo y | sdkmanager "build-tools;$ANDROID_BUILD_TOOLS_VERSION" && \
mv ~/.android .android && \
chown -R 1300:1301 .android
ENV PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools

#====================================
# Install latest nodejs, npm, appium
# Using this workaround to install Appium -> https://github.com/appium/appium/issues/10020 -> Please remove this workaround asap
#====================================
ENV NODE_VERSION=18
ENV APPIUM_VERSION=2.11.4
RUN curl -sL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash \
&& apt-get -qqy install nodejs \
&& npm install -g appium@${APPIUM_VERSION} \
&& exit 0 \
&& npm cache clean
# && apt-get remove --purge -y npm \
# && apt-get autoremove --purge -y \
# && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
# && apt-get clean

#====================================================
# Fix permission issue to download e.g. chromedriver
#====================================================
RUN chown -R 1300:1301 /usr/lib/node_modules/appium

#==============
# Copy scripts
#==============
ENV SCRIPT_PATH="appium-docker-android"
RUN mkdir -p ${SCRIPT_PATH}
COPY start.sh \
generate_selenium_config.sh \
wireless_autoconnect.sh \
wireless_connect.sh \
${SCRIPT_PATH}/
RUN chown -R 1300:1301 ${SCRIPT_PATH}
ENV APP_PATH=/home/androidusr/${SCRIPT_PATH}

#==================
# Use created user
#==================
USER 1300:1301

#===============================
# Install basic Android drivers
#===============================
ENV APPIUM_DRIVER_ESPRESSO_VERSION="3.5.0"
ENV APPIUM_DRIVER_FLUTTER_VERSION="2.9.2"
ENV APPIUM_DRIVER_FLUTTER_INTEGRATION_VERSION="1.1.3"
ENV APPIUM_DRIVER_GECKO_VERSION="1.4.0"
ENV APPIUM_DRIVER_UIAUTOMATOR2_VERSION="3.8.0"
RUN appium driver install --source=npm appium-espresso-driver@${APPIUM_DRIVER_ESPRESSO_VERSION} && \
appium driver install --source=npm appium-flutter-driver@${APPIUM_DRIVER_FLUTTER_VERSION} && \
appium driver install --source=npm appium-flutter-integration-driver@${APPIUM_DRIVER_FLUTTER_INTEGRATION_VERSION} && \
appium driver install --source=npm appium-geckodriver@${APPIUM_DRIVER_GECKO_VERSION} && \
appium driver install --source=npm appium-uiautomator2-driver@${APPIUM_DRIVER_UIAUTOMATOR2_VERSION}

#===============
# Expose Port
#---------------
# 4723
# Appium port
#===============
EXPOSE 4723

#==============
# Start script
#==============
CMD ./${SCRIPT_PATH}/start.sh

Kalıp oluşturmak için:

docker build -t "appium/appium:noble" -f Appium/Dockerfile Appium

Eğer hazır appium/appium kalıbından bir konteyner kullanacaksanız önce USB aygıtını konteynere bağlayarak (-v /dev/bus/usb:/dev/bus/usb) başlatmanız gerekiyor:

$ docker run -d \
--name ccc \
--privileged \
--rm \
-p 4723:4723 \
-v /dev/bus/usb:/dev/bus/usb \
appium/appium

-d Anahtarıyla başlatıyorum çünkü appium kalıbının başlarken bir kabuk betiğini çalıştırması gerekiyor. -it anahtarı verseydim en sona yazacağım komut ile bu betiği ezmiş olacaktım.

--privileged anahtarı ile konteynerin Ubuntu host içinde erişim yetkisini root seviyesine çekiyorum.

--rm bayrağı ile konteyneri durdurursam otomatik silinmesini sağlıyorum

-p anahtarı ile host içinden konteynerin appium sunucusuna isteklerin gelmesini sağlayacak port yönlendirmeyi faal hale getiriyorum.

-v /dev/bus/usb:/dev/bus/usb ile USB aygıtına erişim sağlayan dosyayı konteynerin içine bağlıyorum ki adb komutları bu aygıt üzerinden işleyebilsin

Unutmayın! Eğer Windows 11 makinenizde yahut Ubuntu sanal sunucunuzda adb’nin sunucusu çalışıyorsa konteynerde adb devices komutu işe yaramayacaktır. Sadece adb komutlarının koşmasını istediğiniz yerde adb start-server komutunu çalıştırmalı, diğer ortamlarda adb kill-server komutunu koşturmalısınız.

Konteynere terminalinizi bağlayarak adb devices komutunu çalıştırmanız yeterli olacak:

Konteyneri kapattığımda WSL artık cihazınızı görebilecek ancak telefonunuzda her bağlandığınız yeni makine için ekrana gelecek diyalog kutusuna onay vermeniz gerekiyor:

devcontainer İle Konteynerde Geliştirme Yapmak

Eğer appium geliştirmesini konteyner içinde yapmak istereseniz aşağıdaki dizin dosya yapısında ve dosya içeriklerinde bir klasör oluşturmanız yeterli olacak:

cemt@PC-CEM-TOPKAYA:~/_REPOSITORIES/_APPIUM/pressTheButton$ ll
total 20
drwxr-xr-x 5 cemt cemt 4096 Dec 6 01:48 ./
drwxr-xr-x 3 cemt cemt 4096 Dec 6 01:23 ../
drwxr-xr-x 2 cemt cemt 4096 Dec 6 01:25 .devcontainer/
drwxr-xr-x 2 cemt cemt 4096 Dec 6 02:20 java/
drwxr-xr-x 2 cemt cemt 4096 Dec 6 01:51 python/
cemt@PC-CEM-TOPKAYA:~/_REPOSITORIES/_APPIUM/pressTheButton$ tree
.
├── java
│ └── pom.xml
└── python
├── main.py
└── requirements.txt

3 directories, 3 files

devcontainer.json:

// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/python
{
"name": "Appium Development",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
// "image": "appium/appium:noble"
"build": {
"dockerfile": "Dockerfile"
},

"runArgs": ["--privileged"],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [4723],

"mounts": [
"source=/dev/bus/usb,target=/dev/bus/usb,type=bind"
],
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "pip3 install --user -r ./python/requirements.txt && mvn install -f ./java/pom.xml",
"postCreateCommand": "mvn install -f ./java/pom.xml",

// Configure tool-specific properties.
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"extensions": [
"ms-python.vscode-pylance",
"ms-python.pylint",
"vscjava.vscode-java-pack",
"Oracle.oracle-java",
"GitHub.copilot",
"GitHub.copilot-chat"
]
}
},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
"remoteUser": "root"
}

Ben appium/appium:noble ismiyle ürettiğim kalıbın içinde kod geliştirmek istedim. Ama siz Dockerfile dosyasını güncelleyerek devam edebilirsiniz.

--

--

Cem Topkaya
Cem Topkaya

Written by Cem Topkaya

Evlat, kardeş, ağabey, eş, baba, müzik sever, öğrenmek ister, paylaşmaya can atar, iyi biri olmaya çalışır, hakkı geçenlerden helallik ister vs.

No responses yet