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
Related
im trying to create bash script to install split APKs manually with adb shell
that requires to get session id using the command bellow
command
SESSION='pm install-create -S 42211368'
this will output something like : Success: created install session [547376362]
547376362 will be the session ID
I want to pass 547376362 into SESSION Variable
sh < pm install-write -S 24628703 ${SESSION} 0 /sdcard/YTAPKM/base.apk
so result shall be "sh < pm install-write -S 24628703 547376362 0 /sdcard/YTAPKM/base.apk"
grep is sufficient for this.
SESSION=$(pm install-create -S 42211368 | grep -oE '[0-9]+')
sh < pm install-write -S 24628703 ${SESSION} 0 /sdcard/YTAPKM/base.apk
To explain what's happening a bit:
grep -E uses "extended" regular expressions (easier to work with)
grep -o outputs only the matching part, the integer in this case
SESSION=$(some_cmd) stores the stdout from some_cmd to the variable SESSION, and allows for pipes and such too
I am wanting to extract out the package name of my apk for a script.
I can list the package name with something like this
./aapt dump badging <apk.path> | grep package
The output looks like this
package: name='com.example.app' versionCode='' versionName='4.6.10' platformBuildVersionName='6.0-2166767'
so I want to run the aapt command and it only return com.example.app
I figured it would be something like, but still returns everything.
./aapt dump badging <apk.path> | egrep package:\ name='(.*?)'
Use grep again:
grep -Po "(?<=name=')[^']*" file
This uses Perl regex to print only what comes after name=' and up to the following '.
Test
$ cat a
package: name='com.example.app' versionCode='' versionName='4.6.10' platformBuildVersionName='6.0-2166767'
buuu
$ grep -Po "(?<=name=')[^']*" a
com.example.app
Got it working by doing multiple greps and some regex. Below worked from me. Not sure if its the best way, but works.
$ aapt dump badging <path.to.apk> | grep package | grep -Eo '[a-z]+\.\w+\.\w+'
$ com.example.app
Is it possible to also display the Log's Package Name in each line?
Using
logcat -v long
leaves exactly the package name field (after PID) empty.
I want to filter the Logs from a specific application with different Tags, just wondering if it is possible.
logcat record does not have a "package name field". Therefore there is no standard/built-in way to filter by it.
Although since Android 7.0 you can use logcat --pid option combined with pidof -s command to filter output by binary/package name:
adb shell "logcat --pid=$(pidof -s <package_name>)"
Replace " with ' for Linux/MacOS
This is my script. A little rusty but still working.
PID=`adb shell ps | grep -i <your package name> | cut -c10-15`;
adb logcat | grep $PID
Actually I have a python script to add more colours, and a while loop to keep monitoring for that process when it gets restarted, but I think you'll get the point.
Option 1
Enter these line by line:
adb shell
su
bash
PKG_PID_LIST_CACHE=$(eval $(pm list packages | cut -d ':' -f 2 | sed 's/^\(.*\)$/echo \"\$\(echo \1\) \$\(pidof \1\)\";/'))
PROC_PID_LIST_CACHE=$(ps -A -o NAME -o PID)
PID_LIST_CACHE=$(echo "$PKG_PID_LIST_CACHE\n$PROC_PID_LIST_CACHE")
function pid2pkg() { pkgName=$(echo "$PID_LIST_CACHE" | grep -w $1 | cut -d ' ' -f1 | head -1); if [ "$pkgName" != "" ] ; then echo $pkgName; else echo "*NOT RUNNING*"; fi }
eval "$(logcat -d | sed -r -e 's/([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +(.*)/\2 \$\(pid2pkg \3\) \5/g' | sed -r -e 's/(.+)/echo -e \"\1\"/g')"
The logcat output will be in the following format:
[Time] [Name] [Type] [Message]
Example:
14:34:59.386 wpa_supplicant E wpa_supplicant: nl80211: Failed to set IPv4 unicast in multicast filter
14:35:02.231 com.android.phone D TelephonyProvider: subIdString = 1 subId = 1
14:35:03.469 android.hardware.wifi#1.0-service E WifiHAL : wifi_get_logger_supported_feature_set: Error -3 happened.
14:35:03.518 system_server I WifiService: getWifiApEnabledState uid=10086
14:35:03.519 dev.ukanth.ufirewall D AFWall : isWifiApEnabled is false
14:35:03.520 system_server I GnssLocationProvider: WakeLock released by handleMessage(UPDATE_NETWORK_STATE, 0, 123)
14:35:03.522 dev.ukanth.ufirewall I AFWall : Now assuming wifi connection
Some system processes don't have packages. system_server and wpa_supplicant for instance. If a package name can't be found, the process name will be displayed instead.
Caveats:
If the process behind a certain PID is not running anymore, you can't get the package/process name anymore.
After a process exited itself or your device restarted, the PIDs may actually be assigned to completely different processes.
So you might want to check for how long the process has actually been running:
ps -e -o pid -o stime -o name
Option 2
If you want the formatting to be a bit more readable, you can copy my logging script to your device and execute it:
better_logging.sh
PKG_PID_LIST_CACHE=$(eval $(pm list packages | cut -d ':' -f 2 | sed 's/^\(.*\)$/echo \"\$\(echo \1\) \$\(pidof \1\)\";/'))
PROC_PID_LIST_CACHE=$(ps -A -o NAME -o PID)
PID_LIST_CACHE=$(echo "$PKG_PID_LIST_CACHE\n$PROC_PID_LIST_CACHE")
MAX_LEN=$(echo "$PID_LIST_CACHE" | cut -d ' ' -f1 | awk '{ if ( length > L ) { L=length} }END{ print L}')
function pid2pkg() {
pkgName=$(echo "$PID_LIST_CACHE" | grep -w $1 | cut -d ' ' -f1 | head -1);
if [ "$pkgName" != "" ] ; then
printf "%-${MAX_LEN}s" "$pkgName";
else
printf "%-${MAX_LEN}s" "<UNKNOWN (NOT RUNNING)>";
fi
}
eval "$(\
logcat -d | \
sed -r -e 's/([^ ]+) +([^ ]+) +([^ ]+) +([^ ]+) +(.*)/\2\ $\(pid2pkg \3\) \5/g' | \
sed -r -e 's/(.+)/echo -e \"\1\"/g' \
)" | \
awk '
function color(c,s) {
printf("\033[%dm%s\033[0m\n",90+c,s)
}
/ E / {color(1,$0);next}
/ D / {color(2,$0);next}
/ W / {color(3,$0);next}
/ I / {color(4,$0);next}
{print}
'
To copy and run it, you can use:
adb push better_logging.sh /sdcard/better_logging.sh
adb shell "bash /sdcard/better_logging.sh"
Output will look like this:
This works with awk.
adb logcat | grep -F "`adb shell ps | grep com.yourpackage | awk '{print $2;}'`"
Can anyone tell how can I get the PID from the output of PS command in Android shell.
For example from the output:
u0_a51 20240 38 132944 22300 ffffffff 40037ebc S com.example.poc_service
pid value 20240 is to be got. I tried
ps -ef | grep com.example.poc_service
but to no avail. Also pgrep is not being recognized.
If you have shell access in Android you can also use pidof:
# pidof com.example.poc_service
20240
However, be careful as there may be multiple processes matching...
Its pretty nasty but it works:
for pid in `ls /proc`; do
cmd=`cat $pid/cmdline 2> /dev/null`;
if [ "X$cmd" == "Xcom.example.poc_service" ]; then
echo $pid;
fi
done
or as one line:
for pid in `ls /proc`; do cmd=`cat $pid/cmdline 2> /dev/null`; if [ "X$cmd" == "X/system/bin/mm-qcamera-daemon" ]; then echo $pid; fi done
Neither grep, egrep, fgrep, rgrep is available in Android.
If you are working on Unix, Linux, Mac or Cygwin, you can pipe the output of adb shell command to get the result you want.
$ adb shell ps |grep settings
system 23846 71 111996 22676 ffffffff 00000000 S com.android.settings
$ adb shell ps |grep settings |awk '{print $2}'
23846
How do I get the android application name from a apk file programatically outside an android environment? I have tried parsing androidmanifest.xml but it only shows the package name ( which may not be very informative at times)
If you are using Linux, this command will give you the application name:
aapt dump badging your.apk | sed -n "s/^application-label:'\(.*\)'/\1/p"
You'll have to install aapt first.
Can also be done with apktool.
#!/bin/sh
if [ -z "$1" ]; then echo ${0##*/} useage: ${0##*/} /path/to/your.apk; exit; fi
APKTOOL=$(which apktool apktool.sh | head -1); if [ -z "$APKTOOL" ]; then echo "Error: Could not locate apktool wrapper script."; exit; fi
TMPDIR="/tmp/apktool"
rm -Rf $TMPDIR
$APKTOOL d -q -f -s --force-manifest -o $TMPDIR $1
LABEL=$(cat $TMPDIR/res/values/strings.xml | grep 'string name="title"' | sed -e 's/.*">//' -e 's/<.*//')
rm -Rf $TMPDIR
echo ${LABEL}