|
#!/usr/bin/env bash |
|
|
|
# Parse manifest for given patterns and print first argument value |
|
# |
|
# @param ... - patterns to find in order |
|
manifest() |
|
{ |
|
while read -r |
|
do |
|
for (( ;; )) |
|
do |
|
case $REPLY in |
|
*$1*) |
|
REPLY=${REPLY##*$1} |
|
shift |
|
(( $# > 0 )) && continue |
|
REPLY=${REPLY%%\"*} |
|
echo "${REPLY#.}" |
|
return |
|
;; |
|
esac |
|
|
|
break |
|
done |
|
done < AndroidManifest.xml |
|
} |
|
|
|
# Print package |
|
package() |
|
{ |
|
manifest 'package=\"' |
|
} |
|
|
|
# Print first activity |
|
activity() |
|
{ |
|
manifest '<activity' 'android:name=\"' |
|
} |
|
|
|
# Clean builds & resources |
|
clean() |
|
{ |
|
ant clean |
|
} |
|
|
|
# Build |
|
# |
|
# @param ... - additional build arguments |
|
build() |
|
{ |
|
ant "${TARGET:-debug}" "$@" |
|
} |
|
|
|
# Build & install |
|
install() |
|
{ |
|
build install |
|
} |
|
|
|
# Uninstall package |
|
# |
|
# @param ... - package name (optional) |
|
uninstall() |
|
{ |
|
adb uninstall "${@:-$(package)}" |
|
} |
|
|
|
# Stress test given application |
|
# |
|
# @param 1 - number of pseudo-random events to send (optional) |
|
# @param 2 - package name of application to test (optional) |
|
stress() |
|
{ |
|
adb shell monkey -p "${2:-$(package)}" -v "${1:-1000}" |
|
} |
|
|
|
# Start given activity |
|
# |
|
# @param 1 - full package and activity name (optional) |
|
start() |
|
{ |
|
adb shell "am start -n ${1:-$(package)/.$(activity)}" |
|
} |
|
|
|
# Build, install & run |
|
run() |
|
{ |
|
local PACKAGE |
|
|
|
PACKAGE=$(package) && |
|
[ "$PACKAGE" ] && |
|
install && |
|
start "${PACKAGE}/.$(activity)" |
|
} |
|
|
|
# Run release, needs key.store & key.name to be set in ant.properties |
|
release() |
|
{ |
|
TARGET=release "${@:-run}" |
|
} |
|
|
|
# Run debug |
|
debug() |
|
{ |
|
TARGET=debug "${@:-run}" |
|
} |
|
|
|
# List available emulators or only the requested one |
|
# |
|
# @param 1 - index of emulator to echo (optional) |
|
emus() |
|
{ |
|
local AVD N=1 I=${1:-0} |
|
|
|
for AVD in ~/.android/avd/*.ini |
|
do |
|
[ -r "$AVD" ] || continue |
|
|
|
AVD=${AVD##*/} |
|
AVD=${AVD%.ini} |
|
|
|
if (( !I )) |
|
then |
|
printf "%3d %s\n" "$N" "$AVD" |
|
elif (( N == I )) |
|
then |
|
echo "$AVD" |
|
break |
|
fi |
|
|
|
(( ++N )) |
|
done |
|
} |
|
|
|
# Fire up given (or last used) emulator |
|
# |
|
# @param 1 - name or number of avd (optional) |
|
# @param ... - arguments for emulator (optional) |
|
emu() |
|
{ |
|
local AVD=$1 |
|
|
|
if [ -z "$AVD" ] || (( AVD > 0 )) &>/dev/null |
|
then |
|
AVD=$(emus "${AVD:-1}" | head -n 1) |
|
fi |
|
|
|
shift |
|
emulator -avd "${AVD%.avd}" "$@" & |
|
} |
|
|
|
# Set up a debugging session for a Android Wear device |
|
wearable() |
|
{ |
|
adb forward tcp:4444 localabstract:/adb-hub |
|
adb connect localhost:4444 |
|
} |
|
|
|
# Print memory info |
|
# |
|
# @param 1 - package name (optional) |
|
mem() |
|
{ |
|
adb shell dumpsys meminfo "${1:-$(package)}" |
|
} |
|
|
|
# Print process statistics (starting with Android 4.4) |
|
# |
|
# @param 1 - package name (optional) |
|
stats() |
|
{ |
|
adb shell dumpsys procstats "${1:-$(package)}" |
|
} |
|
|
|
# Broadcast action |
|
# |
|
# @param 1 - full action name |
|
broadcast() |
|
{ |
|
adb shell am broadcast -a "$1" |
|
} |
|
|
|
# Broadcast new battery status |
|
# |
|
# @param 1 - "low" or "okay" |
|
battery() |
|
{ |
|
broadcast "android.intent.action.BATTERY_$(echo "$1" | |
|
tr '[:lower:]' '[:upper:]')" |
|
} |
|
|
|
# Broadcast new power status |
|
# |
|
# @param 1 - "connected" or "disconnected" |
|
power() |
|
{ |
|
broadcast "android.intent.action.ACTION_POWER_$(echo "$1" | |
|
tr '[:lower:]' '[:upper:]')" |
|
} |
|
|
|
# Make a screen capture and fetch image file |
|
# |
|
# @param 1 - file name of output image (optional) |
|
screencap() |
|
{ |
|
local FILE |
|
FILE="/sdcard/${1:-screencap-$(date +%Y%m%d%H%M%S).png}" |
|
|
|
adb shell screencap -p "$FILE" && |
|
adb pull "$FILE" && |
|
adb shell rm "$FILE" |
|
} |
|
|
|
# Record screen and fetch video file |
|
# |
|
# @param 1 - file name of output video (optional) |
|
# @param 2 - wait time in seconds before pull (optional) |
|
screenrecord() |
|
{ |
|
local FILE |
|
FILE="/sdcard/${1:-screenrecord-$(date +%Y%m%d%H%M%S).mp4}" |
|
|
|
fetch_screenrecord() |
|
{ |
|
echo "Fetching $FILE" |
|
sleep "${2:-1}" |
|
adb pull "$FILE" && adb shell rm "$FILE" |
|
} |
|
|
|
echo 'Press Ctrl+C to stop recording' |
|
trap fetch_screenrecord INT |
|
adb shell screenrecord --verbose "$FILE" |
|
trap - INT |
|
unset fetch_screenrecord |
|
} |
|
|
|
# Dump services of given package |
|
# |
|
# @param 1 - package name (optional) |
|
services() |
|
{ |
|
local PACKAGE FOUND='' |
|
PACKAGE=${1:-$(package)} |
|
|
|
adb shell dumpsys activity services | while read -r |
|
do |
|
if [ $FOUND ] |
|
then |
|
case "$REPLY" in |
|
' *'*) |
|
FOUND= |
|
;; |
|
*) |
|
echo "$REPLY" |
|
;; |
|
esac |
|
else |
|
case "$REPLY" in |
|
*$PACKAGE*) |
|
echo "$REPLY" |
|
FOUND=1 |
|
;; |
|
esac |
|
fi |
|
done |
|
} |
|
|
|
# Echo latest target identifier |
|
latest_target() |
|
{ |
|
android list target -c | grep android | tail -n 1 |
|
} |
|
|
|
# Update existing sources with a build.xml file |
|
update() |
|
{ |
|
[ -r project.properties ] || |
|
if [ -r default.properties ] |
|
then |
|
mv default.properties project.properties |
|
else |
|
cat <<EOF > project.properties |
|
target=$(latest_target) |
|
EOF |
|
fi |
|
|
|
android update project --path . -s |
|
} |
|
|
|
# Create a new android project |
|
# |
|
# @param 1 - full namespace with default activity |
|
# @param 2 - SDK target version (optional) |
|
create() |
|
{ |
|
local P=${1%.} A= |
|
|
|
if (( $# < 1 )) || [[ $P != *.* ]] |
|
then |
|
echo 'error: missing namespace and/or main activity' >&2 |
|
return 1 |
|
fi |
|
|
|
A=${P##*.} |
|
|
|
if [[ $A != [A-Z]* ]] |
|
then |
|
A=MainActivity |
|
else |
|
P=${P%.*} |
|
fi |
|
|
|
android create project \ |
|
--target "${2:-$(latest_target)}" \ |
|
--package "$P" \ |
|
--activity "$A" \ |
|
--path . |
|
} |
|
|
|
# Start intent to view given data |
|
# |
|
# @param 1 - data |
|
view() |
|
{ |
|
adb shell am start \ |
|
-a android.intent.action.VIEW \ |
|
-d "${1:-http://www.google.com}" |
|
} |
|
|
|
# Get APK from a device |
|
# |
|
# @param 1 - application id |
|
apk() |
|
{ |
|
local APK_PATH |
|
APK_PATH=$(adb shell pm path "$1") |
|
APK_PATH=${APK_PATH#*:} |
|
APK_PATH=${APK_PATH%$'\r'} |
|
adb pull "$APK_PATH" |
|
} |
|
|
|
# Print help |
|
# |
|
# @param 1 - name of command |
|
help() |
|
{ |
|
local DESC='' NAME='' |
|
|
|
while read -r |
|
do |
|
case $REPLY in |
|
'') |
|
DESC= |
|
;; |
|
\#\ *) |
|
if [ "$DESC" ] |
|
then |
|
[ "$1" ] && DESC=$DESC${DESC:+$'\n'}$' '${REPLY#*# @param } |
|
else |
|
DESC=${REPLY#*# } |
|
fi |
|
;; |
|
*\(\)) |
|
[ "$DESC" ] || continue |
|
NAME=${REPLY%(*} |
|
[ "$1" ] && [ "$NAME" != "$1" ] && continue |
|
echo "$NAME - $DESC" |
|
DESC= |
|
;; |
|
esac |
|
done < "$0" |
|
} |
|
|
|
if [ "${BASH_SOURCE[0]}" == "$0" ] |
|
then |
|
"${@:-debug}" |
|
fi |