/system/bin/sh: tr: not found - Android Azure Devops pipeline - android

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

Related

CircleCI - Android Emulator Setup times out

I require some assistance in setting up an emulator on CircleCI to test my Android instrumented test.
general:
artifacts:
- /home/ubuntu/buildtest/app/build/outputs/apk/
machine:
environment:
ANDROID_HOME: /usr/local/android-sdk-linux
dependencies:
override:
- echo y | android update sdk --no-ui --all --filter tools,platform-tools,build-tools-26.0.2,android-26,extra-google-google_play_services
- chmod +x gradlew
- ANDROID_HOME=/usr/local/android-sdk-linux ./gradlew dependencies
test:
pre:
- android list targets
- echo no | android create avd -n emulatorwithgoogleapi22 -t 12 --tag google_apis
- echo 'vm.heapSize=512' >> ~/.android/avd/emulatorwithgoogleapi22.ini
- echo 'hw.ramSize=1024' >> ~/.android/avd/emulatorwithgoogleapi22.ini
- cat ~/.android/avd/emulatorwithgoogleapi22.ini
- emulator -avd emulatorwithgoogleapi24 -no-audio -no-window :
background: true
parallel: true
- circle-android wait-for-boot
- adb shell input keyevent 82
- adb shell svc power stayon true
- adb shell settings put global window_animation_scale 0
- adb shell settings put global transition_animation_scale 0
- adb shell settings put global animator_duration_scale 0
override:
- ./gradlew assembleDebug
- ./gradlew connectedAndroidTest
post:
- cp -r app/build/outputs $CIRCLE_ARTIFACTS
- cp -r app/build/outputs/androidTest-results/ $CIRCLE_TEST_REPORTS
Above is the YAML file that i use to build on the server. I tried the previous solutions from various forums, but i am still stuck.
Help?

Differences between "echo $variable" and actual output of it

I'm trying to fix a bash script. The part of relevance is this one:
function do_get_apks {(
mkdir -p apks
cd apks
adb shell pm list packages > installed_packages
adb shell pm list packages -3 > installed_packages_user
while read p; do
# remove trailing 'package'
package=$(echo "${p/package:/}" | tr -d '\r\n')
mkdir "$package"
echo "$package"
echo "adb shell pm path $package"
apkpath=$(adb shell pm path "$package")
echo "$apkpath"
apkpath1=$(echo "$apkpath" | grep "package")
echo "$apkpath1"
apkpath2=$(echo "$apkpath" | grep "package" | tr -d '[[:space:]]')
echo "$apkpath2"
apkpath=$(adb shell pm path "$package" | grep package | tr -d '[[:space:]]')
adb pull ${apkpath/package:/} "$package/"
adb shell dumpsys package "$package" > "$package"/info
done < installed_packages)}
Thing is there are incongruities between the output of the command echo "adb shell pm path $package" where package is com.mobeam.barcodeService which returns a list of all the packages, and the actual content of the command "adb shell pm path com.mobeam.barcodeService", which returns just package:/system/app/BeamService/BeamService.apk (which is the desired output)
It looks like the script is returning a list of packages instead of the desired one. You can test this script with adb and any Android Device.
EDIT: Just to clarify, the error I'm getting is the following one:
adb: error: SendRequest failed: path too long: 3922
adb: error: failed to stat remote object
'com.samsung.android.provider.filterproviderpackage:com.monotype.android.font.rosemarypackage:com.sec.android.app.DataCreatepackage:com.gd.mobicore.papackage:com.sec.android.widgetapp.samsungappspackage:com.google.android.youtubepackage:com.samsung.android.app.galaxyfinderpackage:com.sec.android.app.chromecustomizationspackage:com.android.providers.telephonypackage:com.sec.android.app.parserpackage:com.google.android.googlequicksearchboxpackage:com.vlingo.midaspackage:com.android.providers.calendarpackage:com.osp.app.signinpackage:com.sec.android.directsharepackage:com.samsung.clipboardsaveservicepackage:com.sec.automationpackage:com.android.providers.mediapackage:com.google.android.onetimeinitializerpackage:com.sec.android.widgetapp.digitalclockpackage:com.android.wallpapercropperpackage:com.samsung.android.provider.shootingmodeproviderpackage:com.sec.android.app.wfdbrokerpackage:com.sec.android.app.safetyassurancepackage:com.sec.factory.camerapackage:org.simalliance.openmobileapi.servicepackage:com.sec.usbsettingspackage:com.samsung.android.easysetuppackage:com.android.documentsuipackage:com.android.externalstoragepackage:com.sec.factorypackage:com.android.htmlviewerpackage:com.whatsapppackage:com.android.mms.servicepackage:com.android.providers.downloadspackage:com.qualcomm.qti.auth.sampleauthenticatorservicepackage:com.samsung.ucs.agent.bootpackage:com.sec.android.theme.naturalpackage:com.wsomacppackage:com.sec.android.Kiespackage:com.qapp.secprotectpackage:com.sec.android.app.voicenotepackage:com.sec.android.app.easylauncherpackage:com.samsung.knox.rcp.componentspackage:com.sec.android.widgetapp.easymodecontactswidgetpackage:com.samsung.android.intelligenceservice2package:samsunges.sclubpackage:com.sec.di.SmartSelfShotpackage:com.samsung.android.MtpApplicationpackage:com.sec.android.app.factorykeystringpackage:com.sec.android.app.samsungappspackage:com.sec.android.emergencymode.servicepackage:com.google.android.configupdaterpackage:com.sec.android.app.wlantestpackage:com.sec.android.widgetapp.SPlannerAppWidgetpackage:com.sec.android.widgetapp.activeapplicationwidgetpackage:com.sec.android.app.billingpackage:com.sec.android.app.minimode.respackage:com.android.defcontainerpackage:com.sec.android.daemonapppackage:com.sec.enterprise.knox.attestationpackage:com.android.vendingpackage:com.android.pacprocessorpackage:com.dsi.ant.service.socketpackage:com.sec.android.app.popupuireceiverpackage:com.sec.android.AutoPreconfigpackage:com.sec.android.providers.securitypackage:com.sec.android.provider.badgepackage:com.android.certinstallerpackage:com.samsung.android.securitylogagentpackage:com.android.carrierconfigpackage:com.google.android.marvin.talkbackpackage:com.sec.android.app.taskmanagerpackage:com.samsung.android.app.assistantmenupackage:com.samsung.SMTpackage:com.sec.android.ofviewerpackage:com.samsung.everglades.videopackage:androidpackage:com.android.contactspackage:com.samsung.hs20providerpackage:com.samsung.android.sm.devicesecuritypackage:com.sec.android.casual2package:com.samsung.android.smartfacepackage:com.android.mmspackage:com.android.nfcpackage:com.android.stkpackage:com.sec.knox.foldercontainerpackage:com.android.backupconfirmpackage:com.sec.android.cloudagent.dropboxoobedummypackage:com.samsung.klmsagentpackage:com.samsung.android.app.memopackage:flipboard.apppackage:com.sec.android.app.SecSetupWizardpackage:com.android.statementservicepackage:com.google.android.gmpackage:com.sec.android.app.hwmoduletestpackage:com.sec.bcservicepackage:com.android.calendarpackage:com.sec.modem.settingspackage:com.android.phasebeampackage:com.monotype.android.font.samsungsanspackage:com.sec.android.app.sysscopepackage:com.google.android.instantapps.supervisorpackage:com.sec.android.app.wallpaperchooserpackage:com.sec.android.app.servicemodeapppackage:com.sec.android.preloadinstallerpackage:com.sec.android.widgpackage:/system/app/BeamService/BeamService.apk': File name too long

Trying to run a CI server with an emulator

Has anyone managed to build a stable CI server with an emulator? I've spent most of yesterday on it.
I'm using GitLab CI on a Docker container running on Core OS inside VirtualBox, inside Windows 8.1. Right now the emulator does not start and gives me no obvious message. When I try to run tests it simply tells me that there are no running devices.
My current script does this:
- echo yes | android update sdk -a --no-ui --filter android-22
- echo yes | android update sdk -a --no-ui --filter sys-img-armeabi-v7a-google_apis-22
- echo no | android create avd --name test -t 1 -c 1000M --abi "google_apis/armeabi-v7a" --force
- emulator -avd test -partition-size 2000 -no-skin -no-audio -no-window -force-32bit &
Lastly I run
- ./gradlew :breathcount:connectedBetaDebugAndroidTest
it just tells me that no devices are available, so I added something I found on SO in five minutes.
#!/bin/bash
adb wait-for-device
A=$(adb shell getprop sys.boot_completed | tr -d '\r')
while [ "$A" != "1" ]; do
sleep 2
A=$(adb shell getprop sys.boot_completed | tr -d '\r')
done
adb shell input keyevent 82
This just waits for 20 minutes and no device was found.
Right now I'm considering forwarding the ADB port into Docker and running the emulator directly on the machine. VMs all the way down might be the issue.
You should wait until emulator is booted up before running gradle script. Snippet I have been using so far:
- echo y | android update sdk --all --no-ui --filter "sys-img-armeabi-v7a-google_apis-23"
- echo "no" | android -v create avd --force -n arm -t "android-23" --abi "google_apis/armeabi-v7a"
- emulator64-arm -avd arm -no-audio -no-window -no-boot-anim & adb wait-for-device
- chmod +x ./gradlew
- ./gradlew connectedDebugAndroidTest

Get result code of adb shell command

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

Get Application Name/ Label via ADB Shell or Terminal

I'm developing an application that uses ADB Shell to interface with android devices, and I need some way of printing out the application name or label of an application, given maybe their package name.
In short, I need a way of getting app names (i.e. "Angry Birds v1.0.0") for user installed applications through adb shell.
Any light on the matter? Any help is appreciated on this.
adb shell pm list packages will give you a list of all installed package names.
You can then use dumpsys | grep -A18 "Package \[my.package\]" to grab the package information such as version identifiers etc
just enter the following command on command prompt after launching the app:
adb shell dumpsys window windows | find "mCurrentFocus"
if executing the command on linux terminal replace find by grep
If you know the app id of the package (like org.mozilla.firefox), it is easy.
First to get the path of actual package file of the appId,
$ adb shell pm list packages -f com.google.android.apps.inbox
package:/data/app/com.google.android.apps.inbox-1/base.apk=com.google.android.apps.inbox
Now you can do some grep|sed magic to extract the path : /data/app/com.google.android.apps.inbox-1/base.apk
After that aapt tool comes in handy :
$ adb shell aapt dump badging /data/app/com.google.android.apps.inbox-1/base.apk
...
application-label:'Inbox'
application-label-hi:'Inbox'
application-label-ru:'Inbox'
...
Again some grep magic to get the Label.
A shell script to accomplish this:
#!/bin/bash
# Remove whitespace
function remWS {
if [ -z "${1}" ]; then
cat | tr -d '[:space:]'
else
echo "${1}" | tr -d '[:space:]'
fi
}
for pkg in $(adb shell pm list packages -3 | cut -d':' -f2); do
apk_loc="$(adb shell pm path $(remWS $pkg) | cut -d':' -f2 | remWS)"
apk_name="$(adb shell aapt dump badging $apk_loc | pcregrep -o1 $'application-label:\'(.+)\'' | remWS)"
apk_info="$(adb shell aapt dump badging $apk_loc | pcregrep -o1 '\b(package: .+)')"
echo "$apk_name v$(echo $apk_info | pcregrep -io1 -e $'\\bversionName=\'(.+?)\'')"
done
Inorder to find an app's name (application label), you need to do the following:
(as shown in other answers)
Find the APK path of the app whose name you want to find.
Using aapt command, find the app label.
But devices don't ship with the aapt binary out-of-the-box.
So you will need to install it first. You can download it from here:
https://github.com/Calsign/APDE/tree/master/APDE/src/main/assets/aapt-binaries
Check this guide for complete steps:
How to find an app name using package name through ADB Android?
(Disclaimer: I am the author of that blog post)
This is what I just came up with. It gives a few errors but works well enough for my needs, matching package names to labels.
It pulls copies of all packages into subdirectories of $PWD, so keep that in mind if storage is a concern.
#!/bin/bash
TOOLS=~/Downloads/adt-bundle-linux-x86_64-20130717/sdk/build-tools/19.1.0
AAPT=$TOOLS/aapt
PMLIST=adb_shell_pm_list_packages_-f.txt
TEMP=$(echo $(adb shell mktemp -d -p /data/local/tmp) | sed 's/\r//')
mkdir -p packages
[ -f $PMLIST ] || eval $(echo $(basename $PMLIST) | tr '_' ' ') > $PMLIST
while read line; do
package=${line##*:}
apk=${package%%=*}
name=${package#*=}
copy=packages$apk
mkdir -p $(dirname $copy)
if [ ! -s $copy ]; then # copy it because `adb pull` doesn't see /mnt/expand/
adb shell cp -f $apk $TEMP/copy.apk
adb pull $TEMP/copy.apk $copy
fi
label=$($AAPT dump badging $copy || echo ERROR in $copy >&2 | \
sed -n 's/^application-label:\(.\)\(.*\)\1$/\2/p')
echo $name:$label
done < <(sed 's/\r//' $PMLIST)
adb shell rm -rf $TEMP
So I extremely grateful to jcomeau_ictx for providing the info on how to extract application-label info from apk and the idea to pull apk from phone directly!
However I had to make several alteration to script it self:
while read line; do done are breaking as a result of commands within while loop interacting with stdin/stdout and as a result while loop runs only once and then stops, as it is discussed in While loop stops reading after the first line in Bash - the comment from cmo I used solution provided and switched while loop to use unused file descriptor number 9.
All that the script really need is a package name and adb shell pm list packages -f is really excessive so I changed it to expect a file with packages list only and provided example on how one can get one from adb.
jcomeau_ictx script variant do not take in to account that some packages may have multiple apk associated with them which breaks the script.
And the least and last, I made every variable to start with underscore, it's just something that makes it easier to read script.
So here another variant of the same script:
#!/bin/bash
_TOOLS=/opt/android-sdk-update-manager/build-tools/29.0.3
_AAPT=${_TOOLS}/aapt
#adb shell pm list packages --user 0 | sed -e 's|^package:||' | sort >./packages_list.txt
_PMLIST=packages_list.txt
rm ./packages_list_with_names.txt
_TEMP=$(echo $(adb shell mktemp -d -p /data/local/tmp) | sed 's/\r//')
mkdir -p packages
[ -f ${_PMLIST} ] || eval $(echo $(basename ${_PMLIST}) | tr '_' ' ') > ${_PMLIST}
while read -u 9 _line; do
_package=${_line##*:}
_apkpath=$(adb shell pm path ${_package} | sed -e 's|^package:||' | head -n 1)
_apkfilename=$(basename "${_apkpath}")
adb shell cp -f ${_apkpath} ${_TEMP}/copy.apk
adb pull ${_TEMP}/copy.apk ./packages
_name=$(${_AAPT} dump badging ./packages/copy.apk | sed -n 's|^application-label:\(.\)\(.*\)\1$|\2|p' )
#'
echo "${_package} - ${_name}" >>./packages_list_with_names.txt
done 9< ${_PMLIST}
adb shell rm -rf $TEMP

Categories

Resources