I've read related question
However, I'm using the 'androidx.test:orchestrator:1.4.0', which should not has the bug below 1.2.0.
My case is, I will get error: com.android.build.gradle.internal.testing.ConnectedDevice > No tests found.[GM1910 - 11] FAILED if I enable :
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
I've done the prefix operations:
$ curl -O https://dl.google.com/android/maven2/androidx/test/orchestrator/1.4.0/orchestrator-1.4.0.apk
$ curl -O https://dl.google.com/android/maven2/androidx/test/services/test-services/1.4.0/test-services-1.4.0.apk
$ adb install -r orchestrator-1.4.0.apk
$ adb install -r test-services-1.4.0.apk
$ adb shell 'CLASSPATH=$(pm path androidx.test.services) app_process / \
androidx.test.services.shellexecutor.ShellMain am instrument -w -e \
targetInstrumentation com.example.notroid/androidx.test.runner.AndroidJUnitRunner \
androidx.test.orchestrator/.AndroidTestOrchestrator'
Time: 0
OK (0 tests)
Related
I get the following error when I try to start the emulator from my pipeline in Azure:
nohup $ANDROID_HOME/emulator/emulator -avd xamarin_android_emulator -no-snapshot >
/dev/null 2>&1 &
$ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop
sys.boot_completed | tr -d '\r') ]]; do sleep 1; done; input keyevent 82'
$ANDROID_HOME/platform-tools/adb devices
echo "Emulator started"
Generating script.
##[debug]which 'bash'
##[debug]found: '/bin/bash'
##[debug]Agent.Version=2.204.0
##[debug]agent.tempDirectory=/Users/runner/work/_temp
##[debug]check path : /Users/runner/work/_temp
========================== Starting Command Output ===========================
##[debug]which '/bin/bash'
##[debug]found: '/bin/bash'
##[debug]/bin/bash arg: /Users/runner/work/_temp/52b9227f-faa1-
4557-9396-
8b3c63435983.sh
##[debug]exec tool: /bin/bash
##[debug]arguments:
##[debug] /Users/runner/work/_temp/52b9227f-faa1-4557-9396-
8b3c63435983.sh
/bin/bash /Users/runner/work/_temp/52b9227f-faa1-4557-9396-
8b3c63435983.sh
* daemon not running; starting now at tcp:5037
* daemon started successfully
/system/bin/sh: tr: not found
/system/bin/sh: tr: not found
/system/bin/sh: tr: not found
/system/bin/sh: tr: not found
/system/bin/sh: tr: not found
/system/bin/sh: tr: not found
/system/bin/sh: tr: not found
/system/bin/sh: tr: not found
/system/bin/sh: tr: not found
/system/bin/sh: tr: not found
Given below is my pipeline yml
# Android
# Build your Android project with Gradle.
# Add steps that test, sign, and distribute the APK, save build artifacts, and more:
# https://learn.microsoft.com/azure/devops/pipelines/languages/android
#trigger:
#- feature/azure-cicd
pool:
vmImage: 'macos-latest'
steps:
- bash: |
# Install AVD files
echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-19;google_apis;x86'
echo "AVD system-image successfully downloaded and installed."
displayName: 'Download and install emulator image'
- bash: |
# Create emulator
echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n xamarin_android_emulator -k 'system-images;android-19;google_apis;x86' --force
$ANDROID_HOME/emulator/emulator -list-avds
displayName: 'Create emulator'
- bash: |
# Start emulator in background
nohup $ANDROID_HOME/emulator/emulator -avd xamarin_android_emulator -no-snapshot > /dev/null 2>&1 &
$ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 1; done; input keyevent 82'
$ANDROID_HOME/platform-tools/adb devices
echo "Emulator started"
displayName: 'Start emulator'
- bash: |
./gradlew testdevelopDebug connectedMockDebugAndroidTest --stacktrace --no-daemon
./gradlew --stop
displayName: 'Run Instrumented Tests'
continueOnError: true
This works perfect when I use android-28 instead of android-19
Is there any change that I need to make in my pipeline such that I can launch the emulator?
Any help is much appreciated
The adb call in yml was done to get the status and check that locally. In the yml I was trying to pass the while loop into adb.
This example depicts the right usage and solution:
https://stackoverflow.com/a/38896494/
while [ "`adb shell getprop sys.boot_completed | tr -d '\r' `" != "1" ] ; do sleep 1; done
I'm trying to build a prototype Android app for connecting my Android device to an iOS device wirelessly. While researching for options, I came across libimobiledevice library which seems like the right fit. I'm currently stuck in what seems like iOS device is receiving the request but rejecting it and that's what I wanted to understand from this forum.
What I have done so far:
I have packaged libimobiledevice library as an .so file in my Android application and I able to make JNI calls from my Android app to call in methods of the library.
I'm also packaging in the libusbmuxd library and libplist as mentioned in the dependencies.
For protoyping, I'm creating a wifi hotspot from my Android device and connecting the iOS device. I also know the IP addresses of the two devices. I also know that the lockdownd deamon on iOS runs on port 62078. Given the IP address and port, when I make the call to the socket I do see that the idevice_new_with_options -> usbmuxd_get_device -> connect_usbmuxd_socket -> socket_connect is able to reach out to iOS device on the socket. Confirmed by looking at iOS logs
lockdownd[70] <Notice>: _receive_message: <private>
symptomsd(SymptomEvaluator)[120] <Notice>: Data Usage for lockdownd - WiFi in/out: 181637370/198768065, WiFi delta_in/delta_out: 458/0, Cell in/out: 0/0, Cell delta_in/delta_out: 0/0, RNF: 0, subscriber tag: 0
But immediately after this I see that the connection is dropped probably because lockdownd is rejecting it. I see the this getting triggered with error 104 which means "Connection reset by peer"
Questions:
As I understand it, the libimobiledevice is trying to make a TCP/IP connection to iPhone. And once the connection succeeds, I'll be able to use the rest of the capabilities of the library like invoking the mentioned services.
Is my setup correct or am I missing something? The code compiles and doesn't crash so it feels like I have all the needed dependencies.
How can I debug this further on iOS side to understant why lockdownd is reseting the connection?
Thanks!
libimobiledevice depends on usbmux, and for Linux this is not currently working wirelessly. You can overcome this by using the usbmuxd2 re-implementation.
This is my script for getting that full linux implementation up and running on a raspberry Pi. I also have a more user friendly walk through of the same thing right here: nMirrior
#!/bin/bash
echo "installing dependencies"
read -p "Do you want to update/install build tools (you need to if this is a new image) (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
sudo apt-get -q update
sudo apt-get -q install \
build-essential \
checkinstall \
git \
autoconf \
automake \
libtool-bin
fi
echo "installing libatomic"
sudo apt-get -q install libatomic-ops-dev libatomic1
echo "installing libimobiledevice dependencies"
sudo apt-get -q install \
libplist-dev \
libusbmuxd-dev \
libimobiledevice-dev \
libusb-1.0-0-dev \
libplist++-dev \
libssl-dev \
usbmuxd \
udev \
libavahi-client-dev \
avahi-utils
echo "Starting nMirror setup"
# Configure source directories
nMirrorDir=~/nMirror
echo "The applications needed for nMirror will be installed in $nMirror"
libplistDir=$nMirrorDir/libplist
libusbmuxdDir=$nMirrorDir/libusbmuxd
libimobiledeviceDir=$nMirrorDir/libimobiledevice
libgeneralDir=$nMirrorDir/libgeneral
usbmuxd2Dir=$nMirrorDir/usbmuxd2
#Standard libimobiledevice repos
libplistGit=https://github.com/libimobiledevice/libplist.git
libusbmuxdGit=https://github.com/libimobiledevice/libusbmuxd.git
libimobiledeviceGit=https://github.com/libimobiledevice/libimobiledevice.git
#tihmstar repo for usbmuxd2 to support network connection to iDevice
usbmuxd2Git=https://github.com/tihmstar/usbmuxd2.git
libgeneralGit=https://github.com/tihmstar/libgeneral.git
# Create the project directory if it does not exist
mkdir -p $nMirrorDir
cd $nMirrorDir
# Fetch the repos
fetchnext=false
if test -d $libplistDir; then
read -p "libplist directory exists. Remove and re-fetch new? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
rm -rf $libplistDir
fetchnext=true
fi
else
fetchnext=true
fi
if [ "$fetchnext" == true ]; then
echo "Cloning from git. 1 - libplist"
cd $nMirrorDir
git clone --quiet $libplistGit
cd $libplistDir
# git checkout 2.2.0 # Cannot go back to the last tag (2.2.0) because usbmuxd2 want 2.2.1 - just get the head for now
fi
if test -d $libusbmuxdDir; then
read -p "libusbmuxd directory exists. Remove and re-fetch new? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
rm -rf $libusbmuxdDir
fetchnext=true
fi
else
fetchnext=true
fi
if [ "$fetchnext" == true ]; then
echo "Cloning from git. 2 - libusbmuxd (Normal)"
cd $nMirrorDir
git clone --quiet $libusbmuxdGit
cd $libusbmuxdDir
git checkout 2.0.2
fi
if test -d $libimobiledeviceDir; then
read -p "libimobiledevice directory exists. Remove and re-fetch new? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
rm -rf $libimobiledeviceDir
fetchnext=true
fi
else
fetchnext=true
fi
if [ "$fetchnext" == true ]; then
echo "Cloning from git. 3 - libimobiledevice"
cd $nMirrorDir
git clone --quiet $libimobiledeviceGit
cd $libimobiledeviceDir
git checkout 1.3.0
fi
#tihmstar repo for usbmuxd2 to support network connection to iDevice
if test -d $libgeneralDir; then
read -p "libgeneral directory exists. Remove and re-fetch new? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
rm -rf $libgeneralDir
fetchnext=true
fi
else
fetchnext=true
fi
if [ "$fetchnext" == true ]; then
echo "Cloning from git. 4 - libgeneral (tihmstar Experimental repo tag 55)"
cd $nMirrorDir
git clone --quiet $libgeneralGit
cd $libgeneralDir
git checkout 55
fi
if test -d $usbmuxd2Dir; then
read -p "usbmuxd2 directory exists. Remove and re-fetch new? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
rm -rf $usbmuxd2Dir
fetchnext=true
fi
else
fetchnext=true
fi
if [ "$fetchnext" == true ]; then
echo "Cloning from git. 5 - usbmuxd2 (tihmstar Eperimental repo)"
cd $nMirrorDir
git clone --quiet $usbmuxd2Git
cd $usbmuxd2Dir
git submodule init
git submodule update
fi
#build stage
cd $libplistDir
./autogen.sh
make
sudo make install
cd $libusbmuxdDir
./autogen.sh
make
sudo make install
cd $libimobiledeviceDir
./autogen.sh
make
sudo make install
sudo ldconfig
#configure Avahi for zeroconf as per https://www.raspberrypi.org/forums/viewtopic.php?t=267113
#Note: Zeroconf may not be desirable - use with caution
cd $nMirrorDir
#create avahi patch
tee avahi.patch <<EOF
--- /etc/avahi/avahi-daemon.conf 2021-08-16 23:59:16.917672251 +0100
+++ /etc/avahi/avahi-daemon_usbmuxd.conf 2021-08-17 09:45:02.096575347 +0100
## -20,7 +20,7 ##
[server]
#host-name=foo
-#domain-name=local
+domain-name=local
#browse-domains=0pointer.de, zeroconf.org
use-ipv4=yes
use-ipv6=yes
## -46,8 +46,8 ##
#disable-user-service-publishing=no
#add-service-cookie=no
#publish-addresses=yes
-publish-hinfo=no
-publish-workstation=no
+publish-hinfo=yes
+publish-workstation=yes
#publish-domain=yes
#publish-dns-servers=192.168.50.1, 192.168.50.2
#publish-resolv-conf-dns-servers=yes
EOF
cd /etc
sudo patch -p2 < $nMirrorDir/avahi.patch
#enable the avahi-daemon
systemctl list-unit-files avahi-daemon.service
#activate/enable the avahi-daemon.service
sudo systemctl enable avahi-daemon.service
sudo systemctl start avahi-daemon.service
sudo systemctl restart avahi-daemon.service
#enable ssh service
sudo systemctl enable ssh.service
sudo systemctl start ssh.service
#avahi-browse -a
# if using gcc: the patch below works to include -latomic
# if using clang: make CXX=clang++
cd $libgeneralDir
./autogen.sh
make CFLAGS="-g -O2 -std=c11 -latomic" LDFLAGS=-latomic
sudo make install
sudo ldconfig
cd $usbmuxd2Dir
#create log patch
#cassure only needed for versions after 55 - probably remove this as checkout is fixed to 55
tee log.patch <<EOF
--- a/configure.ac
+++ b/configure.ac
## -29,7 +29,7 ## case $host_os in
have_mdns="yes"
;;
*)
- LDFLAGS+=" -lstdc++fs"
+ LDFLAGS+="-latomic -lstdc++fs"
;;
esac
EOF
git apply log.patch
./autogen.sh
make
sudo make install
sudo ldconfig
# get the BT PAN up and running
sudo apt-get install bluez-tools
sudo tee /etc/systemd/network/pan0.netdev <<EOF
[NetDev]
Name=pan0
Kind=bridge
EOF
sudo tee /etc/systemd/network/pan0.network <<EOF
[Match]
Name=pan0
[Network]
Address=172.20.1.1/24
DHCPServer=yes
EOF
sudo tee /etc/systemd/system/bt-agent.service <<EOF
[Unit]
Description=Bluetooth Auth Agent
[Service]
#ExecStart=/usr/bin/bt-agent -c NoInputNoOutput
ExecStart=/bin/sh -c '/usr/bin/yes | /usr/bin/bt-agent --capability=NoInputNoOutput' #autoaccept
Type=simple
[Install]
WantedBy=multi-user.target
EOF
sudo tee /etc/systemd/system/bt-network.service <<EOF
[Unit]
Description=Bluetooth NEP PAN
After=pan0.network
[Service]
ExecStart=/usr/bin/bt-network -s nap pan0
Type=simple
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable systemd-networkd
sudo systemctl enable bt-agent
sudo systemctl enable bt-network
sudo systemctl start systemd-networkd
sudo systemctl start bt-agent
sudo systemctl start bt-network
sudo bt-adapter --set Discoverable 1
# list devices. Need to ask the user to connect via USB the first time using idevicesyslog. Then make the BT PAN connection and connect via idevicesyslog -n
/usr/local/bin/idevice_id
Im trying to run android emulator on docker but I get the following error, I have done some research but none of the answers helped me in achieving my goal, here is the error that I get and my docker file, I have tried armeabi and system-images;android-29;google_apis;x86 and both did not work.
# emulator -avd device
emulator: WARNING: encryption is off
emulator: INFO: QtLogger.cpp:68: Warning: could not connect to display ((null):0, (null))
emulator: INFO: QtLogger.cpp:68: Info: Could not load the Qt platform plugin "xcb" in "/opt/android-sdk/emulator/lib64/qt/plugins" even though it was found. ((null):0, (null))
Fatal: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: xcb.
((null):0, (null))
emulator: INFO: QtLogger.cpp:68: Fatal: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: xcb.
((null):0, (null))
Aborted
Im doing the same steps on my MAC and it's working fine, here is my docker file:
FROM ubuntu:18.04
RUN dpkg --add-architecture i386 && \
apt-get update -y && \
apt-get install -y --no-install-recommends libncurses5:i386 libc6:i386 libstdc++6:i386 lib32gcc1 lib32ncurses5 lib32z1 zlib1g:i386 && \
apt-get install -y --no-install-recommends openjdk-8-jdk && \
apt-get install -y --no-install-recommends git wget unzip && \
apt-get install -y --no-install-recommends qt5-default
ARG GRADLE_VERSION=5.2.1
ARG GRADLE_DIST=bin
RUN cd /opt && \
wget -q https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-${GRADLE_DIST}.zip && \
unzip gradle*.zip && \
ls -d */ | sed 's/\/*$//g' | xargs -I{} mv {} gradle && \
rm gradle*.zip
# download and install Android SDK
# https://developer.android.com/studio/#downloads
ARG ANDROID_SDK_VERSION=4333796
ENV ANDROID_HOME /opt/android-sdk
RUN mkdir -p ${ANDROID_HOME} && cd ${ANDROID_HOME} && \
wget -q https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_VERSION}.zip && \
unzip *tools*linux*.zip && \
rm *tools*linux*.zip
# set the environment variables
ENV APK_SIGNER=/opt/android-sdk/build-tools/29.0.2/
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
ENV ANDROID_SDK_ROOT /opt/android-sdk
ENV GRADLE_HOME /opt/gradle
ENV PATH ${PATH}:${GRADLE_HOME}/bin:${ANDROID_HOME}/emulator:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/tools/bin/apksigner:${APK_SIGNER}
ENV _JAVA_OPTIONS -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
# WORKAROUND: for issue https://issuetracker.google.com/issues/37137213
ENV LD_LIBRARY_PATH ${ANDROID_HOME}/emulator/lib64:${ANDROID_HOME}/emulator/lib64/qt/lib
# accept the license agreements of the SDK components
ADD docker/license_accepter.sh /opt/
RUN chmod +x /opt/license_accepter.sh && /opt/license_accepter.sh $ANDROID_HOME
# setup adb server
EXPOSE 5037
# install and configure SSH server
EXPOSE 22
ADD docker/sshd-banner /etc/ssh/
ADD docker/authorized_keys /tmp/
RUN apt-get update -y && \
apt-get install -y --no-install-recommends openssh-server supervisor locales && \
mkdir -p /var/run/sshd /var/log/supervisord && \
locale-gen en en_US en_US.UTF-8 && \
apt-get remove -y locales && apt-get autoremove -y && \
FILE_SSHD_CONFIG="/etc/ssh/sshd_config" && \
echo "\nBanner /etc/ssh/sshd-banner" >> $FILE_SSHD_CONFIG && \
echo "\nPermitUserEnvironment=yes" >> $FILE_SSHD_CONFIG && \
ssh-keygen -q -N "" -f /root/.ssh/id_rsa && \
FILE_SSH_ENV="/root/.ssh/environment" && \
touch $FILE_SSH_ENV && chmod 600 $FILE_SSH_ENV && \
printenv | grep "JAVA_HOME\|GRADLE_HOME\|ANDROID_HOME\|LD_LIBRARY_PATH\|PATH" >> $FILE_SSH_ENV && \
FILE_AUTH_KEYS="/root/.ssh/authorized_keys" && \
touch $FILE_AUTH_KEYS && chmod 600 $FILE_AUTH_KEYS && \
for file in /tmp/*.pub; \
do if [ -f "$file" ]; then echo "\n" >> $FILE_AUTH_KEYS && cat $file >> $FILE_AUTH_KEYS && echo "\n" >> $FILE_AUTH_KEYS; fi; \
done && \
(rm /tmp/*.pub 2> /dev/null || true)
ADD docker/supervisord.conf /etc/supervisor/conf.d/
ADD docker/supervisord.conf /etc/supervisor/conf.d/
ADD docker/android.keystore /Android-APK/
ADD app/build/outputs/apk/release/ /Android-APK/
RUN sdkmanager "platform-tools" "platforms;android-29" "build-tools;29.0.2" "add-ons;addon-google_apis-google-24"
RUN apksigner sign --ks /Android-APK/android.keystore --ks-pass pass:android --key-pass pass:android --in /Android-APK/app-release-unsigned.apk --out /Android-APK/signed-app.apk
RUN zipalign -f 4 /Android-APK/signed-app.apk /Android-APK/aligned-app.apk
#RUN sdkmanager "system-images;android-23;google_apis;x86"
#RUN adb install /Android-APK/aligned-app.apk
#RUN sdkmanager "system-images;android-25;google_apis;arm64-v8a"
#RUN avdmanager create avd --force --name "device" --abi "arm64-v8a" --package 'system-images;android-25;google_apis;arm64-v8a' --device "Nexus 10"
CMD ["/usr/bin/supervisord"]
I had a similar problem, and it ended up being that our script was running the incorrect version of the emulator (26, which doesn't have good support for headless yet)
It should be running
$ANDROID_HOME/emulator/emulator -avd avd-name -no-skin -no-audio -no-window
and not the emulator in the tools folder.
Check the version of the emulator by just running the executable. My output (that works) is
emulator: Android emulator version 30.4.5.0 (build_id 7140946) (CL:N/A)
emulator: ERROR: No AVD specified. Use '#foo' or '-avd foo' to launch a virtual device named 'foo'
first run
xhost +
then run your docker container like this
docker run -i -t --net=host --privileged --env="DISPLAY" \
-v $HOME/.Xauthority:/root/.Xauthority:rw \
-v ~/disk1/android_docker:/home/android \
android-image /bin/bash
then you can run
emulator
I am trying to automate Android Builds and Tests. The instrumentation test is not working because I get the following error while starting the android emulator in the Docker Runner:
Running with gitlab-ci-multi-runner 9.4.2 (6d06f2e) ...
Using Docker executor with image kmindi/android-ci:latest ...
...
$ chmod +x ./gradlew
$ echo no | avdmanager -v create avd --force --name test --abi google_apis/x86_64 --package 'system-images;android-25;google_apis;x86_64'
Do you wish to create a custom hardware profile? [no] $ export SHELL=/bin/bash && echo "no" | emulator -avd test -noaudio -no-window -gpu off -verbose -qemu
sh: 1: file: not found
sh: 1: file: not found
WARNING: Cannot decide host bitness because $SHELL is not properly defined; 32 bits assumed.
ERROR: 32-bit Linux Android emulator binaries are DEPRECATED, to use them
you will have to do at least one of the following:
- Use the '-force-32bit' option when invoking 'emulator'.
- Set ANDROID_EMULATOR_FORCE_32BIT to 'true' in your environment.
Either one will allow you to use the 32-bit binaries, but please be
aware that these will disappear in a future Android SDK release.
Consider moving to a 64-bit Linux system before that happens.
ERROR: Job failed: exit code 1
I created the following Dockerfile (https://hub.docker.com/r/kmindi/android-ci/)
FROM openjdk:8-jdk
ENV ANDROID_BUILD_TOOLS "26.0.1"
ENV ANDROID_SDK_TOOLS "25.2.5"
ENV ANDROID_HOME "/android-sdk"
ENV PATH=$PATH:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools
# Prepare dependencies
RUN mkdir $ANDROID_HOME \
&& apt-get update --yes \
&& apt-get install --yes wget tar unzip lib32stdc++6 lib32z1 libqt5widgets5 expect \
&& apt-get clean \
&& rm -fr /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Install sdk tools
RUN wget -O android-sdk.zip https://dl.google.com/android/repository/tools_r${ANDROID_SDK_TOOLS}-linux.zip \
&& unzip -q android-sdk.zip -d $ANDROID_HOME \
&& rm android-sdk.zip
# Workaround for
# Warning: File /root/.android/repositories.cfg could not be loaded.
RUN mkdir /root/.android \
&& touch /root/.android/repositories.cfg
# Workaround for host bitness error with android emulator
# https://stackoverflow.com/a/37604675/455578
RUN mv /bin/sh /bin/sh.backup \
&& cp /bin/bash /bin/sh
# Add tools from travis
ADD https://raw.githubusercontent.com/travis-ci/travis-cookbooks/ca800a93071a603745a724531c425a41493e70ff/community-cookbooks/android-sdk/files/default/android-wait-for-emulator /usr/local/bin/android-wait-for-emulator
RUN chmod +x /usr/local/bin/android-wait-for-emulator
# Add own tools
COPY assure_emulator_awake.sh /usr/local/bin/assure_emulator_awake.sh
RUN chmod +x /usr/local/bin/assure_emulator_awake.sh
# Update platform and build tools
RUN echo "y" | sdkmanager "tools" "platform-tools" "build-tools;${ANDROID_BUILD_TOOLS}"
# Update SDKs
RUN echo "y" | sdkmanager "platforms;android-26" "platforms;android-25"
# Update emulators
RUN echo "y" | sdkmanager "system-images;android-25;google_apis;x86_64"
# Update extra
RUN echo "y" | sdkmanager "extras;android;m2repository" "extras;google;m2repository" "extras;google;google_play_services"
# Constraint Layout
RUN echo "y" | sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2"
RUN echo "y" | sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout-solver;1.0.2"
In GitLab I use the following .gitlab-ci.yml:
image: kmindi/android-ci:latest
variables:
ANDROID_COMPILE_SDK: "25"
before_script:
- chmod +x ./gradlew
stages:
- build
- test
build:
stage: build
script:
- ./gradlew assembleDebug
artifacts:
name: "App_{$CI_BUILD_ID}"
expire_in: 1 week
paths:
- "app/build/outputs/apk/**/*.apk"
except:
- tags
test:unit:
stage: test
script:
- ./gradlew test jacoco
artifacts:
name: "tests-unit-${CI_BUILD_NAME}_${CI_COMMIT_REF_NAME}_${CI_BUILD_REF}"
expire_in: 1 week
paths:
- "**/build/reports/**"
test:instrumentation:25:
stage: test
script:
- echo no | avdmanager -v create avd --force --name test --abi google_apis/x86_64 --package 'system-images;android-25;google_apis;x86_64'
- export SHELL=/bin/bash && echo "no" | emulator -avd test -noaudio -no-window -gpu off -verbose -qemu &
- adb wait-for-device
- android-wait-for-emulator
- export TERM=${TERM:-dumb}
- assure_emulator_awake.sh "./gradlew cAT"
- ./gardlew createDebugCoverageReport
artifacts:
name: "tests-instrumentation-${ANDROID_COMPILE_SDK}-${CI_BUILD_NAME}"
expire_in: 1 week
paths:
- "**/build/reports/**"
The workaround proposed in https://stackoverflow.com/a/37604675/455578 (chaning of bash/sh) is not working (applied in the Dockerfile). Also setting the SHELL variable does not help. If I use emulator64-x86 instead of emulator I get the error command not found.
What am I missing?
Do I have to install other packages via apt?
Maybe it originates in the used openjdk-8 / debian stretch docker image?
Thanks :)
With SDK Revision 25.3.0 (March 2017) emulator was released separately from the SDK Tools (https://developer.android.com/studio/releases/emulator.html#25-3).
Practically it means that now there is a new ${ANDROID_HOME}/emulator folder which you have to add to PATH. (NOTE: it has to be added before tools folder, because for whatever reason old tools/emulator binary is still there). Example:
ENV PATH ${ANDROID_HOME}/emulator:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools:${PATH}
How should I get $? of adb shell <command>?
I would like to check the result of adb shell mkdir /xxx.
I executed mkdir command by adb shell and failed but the result of $? is 0.
$ adb shell mkdir /xxx
mkdir failed for /xxx, Read-only file system
$ adb shell echo $?
0
$ adb shell "mkdir /xxx; echo $?"
mkdir failed for /xxx, Read-only file system
0
I would like to get the result code of adb shell <command> but not in the interactive mode like below:
$ adb shell
shell#android:/ $ mkdir /xxx
mkdir failed for /xxx, Read-only file system
255|shell#android:/ $ echo $?
255
You should do:
$ adb shell 'mkdir /xxx; echo $?'
mkdir failed for /xxx, Read-only file system
255
Notice the single quotes, otherwise $? is evaluated before reaching adb.
If you are using an older emulator, then adb shell does not return the exit value. Then you have to use adb shell 'false; echo $?' like in https://stackoverflow.com/a/17480194/306864
In newer emulators, it works properly, then you can do adb shell false || echo failed. Here's how I tested:
$ adb -e android-22 shell false; echo $?
0
$ adb -e android-22 shell 'false; echo $?'
1
$ adb -e android-29 shell false; echo $?
1
$ adb -e android-29 shell 'false; echo $?'
1