chautob0t chautob0t - 22 days ago 5
Python Question

Print apk versionCode using aapt using python subprocess library

I need to know the versionCode of APK files and for that the following command works perfectly.

./aapt dump badging my.apk | grep versionCode | awk '{print $3}' | sed s/versionCode=//g | sed s/\'//g


Credit for above code - https://gist.github.com/j796160836/6ad39ba143bf038bfde8

I'd like to know this versionCode in my python script so I use a subprocess call to run the same command but I don't get the correct output.

The output is equivalent to executing
./aapt dump badging my.apk
and no post processing works after that.

Here's my python code -

import subprocess

package = "cn.xender.apk"
test = subprocess.Popen(["./aapt", "dump", "badging", package, "|", "grep", "versionCode", "|", "'awk'", "'{print $3}'", "|", "sed", "s/versionCode=//g", "|", "sed", "s/\'//g"], stdout=subprocess.PIPE)
versionCode = test.communicate()[0]
print versionCode


I have tried to use single quotes and provide escape characters for the quotes present in awk and sed expressions but no change in result.

EDIT - Output of
./aapt dump badging cn.xender


package: name='cn.xender' versionCode='303' versionName='3.3.1025' platformBuildVersionName='6.0-2704002'
install-location:'auto'
sdkVersion:'9'
targetSdkVersion:'23'
uses-permission: name='android.permission.CAMERA'
uses-permission: name='android.permission.WRITE_EXTERNAL_STORAGE'
uses-permission: name='android.permission.READ_EXTERNAL_STORAGE'
uses-permission: name='android.permission.INTERNET'
uses-permission: name='android.permission.ACCESS_WIFI_STATE'
uses-permission: name='android.permission.ACCESS_NETWORK_STATE'
uses-permission: name='android.permission.WAKE_LOCK'
uses-permission: name='android.permission.VIBRATE'
uses-permission: name='android.permission.GET_TASKS'
uses-permission: name='android.permission.REORDER_TASKS'
uses-permission: name='android.permission.WRITE_SETTINGS'
uses-permission: name='android.permission.READ_CONTACTS'
uses-permission: name='android.permission.WRITE_CONTACTS'
uses-permission: name='android.permission.WRITE_PROFILE'
uses-permission: name='android.permission.READ_CALL_LOG'
uses-permission: name='android.permission.WRITE_CALL_LOG'
uses-permission: name='android.permission.WRITE_SMS'
uses-permission: name='android.permission.READ_SMS'
uses-permission: name='android.permission.MOUNT_UNMOUNT_FILESYSTEMS'
uses-permission: name='android.permission.BROADCAST_STICKY'
uses-permission: name='android.permission.CHANGE_WIFI_STATE'
uses-permission: name='android.permission.CHANGE_WIFI_MULTICAST_STATE'
uses-permission: name='android.permission.CHANGE_NETWORK_STATE'
uses-permission: name='android.permission.CHANGE_CONFIGURATION'
uses-permission: name='android.permission.GET_ACCOUNTS'
uses-permission: name='android.permission.ACCESS_COARSE_LOCATION'
uses-permission: name='android.permission.MANAGE_DOCUMENTS'
application-label:'Xender'
application-label-ca:'Xender'
application-label-da:'Xender'
application-label-fa:'Xender'
application-label-ja:'Xender'
application-label-ka:'Xender'
application-label-pa:'Xender'
application-label-ta:'Xender'
application-label-nb:'Xender'
application-label-be:'Xender'
application-label-de:'Xender'
application-label-ne:'Xender'
application-label-te:'Xender'
application-label-af:'Xender'
application-label-bg:'Xender'
application-label-th:'Xender'
application-label-fi:'Xender'
application-label-hi:'Xender'
application-label-si:'Xender'
application-label-vi:'Xender'
application-label-kk:'Xender'
application-label-mk:'Xender'
application-label-sk:'Xender'
application-label-uk:'Xender'
application-label-el:'Xender'
application-label-gl:'Xender'
application-label-ml:'Xender'
application-label-nl:'Xender'
application-label-pl:'Xender'
application-label-sl:'Xender'
application-label-tl:'Xender'
application-label-am:'Xender'
application-label-km:'Xender'
application-label-bn:'Xender'
application-label-en:'Xender'
application-label-in:'Xender'
application-label-kn:'Xender'
application-label-mn:'Xender'
application-label-ko:'Xender'
application-label-lo:'Xender'
application-label-no:'Xender'
application-label-ro:'Xender'
application-label-sq:'Xender'
application-label-ar:'Xender'
application-label-fr:'Xender'
application-label-hr:'Xender'
application-label-mr:'Xender'
application-label-sr:'Xender'
application-label-tr:'Xender'
application-label-ur:'Xender'
application-label-bs:'Xender'
application-label-cs:'Xender'
application-label-es:'Xender'
application-label-is:'Xender'
application-label-ms:'Xender'
application-label-et:'Xender'
application-label-it:'Xender'
application-label-lt:'Xender'
application-label-pt:'Xender'
application-label-eu:'Xender'
application-label-gu:'Xender'
application-label-hu:'Xender'
application-label-ru:'Xender'
application-label-zu:'Xender'
application-label-lv:'Xender'
application-label-sv:'Xender'
application-label-iw:'Xender'
application-label-sw:'Xender'
application-label-hy:'Xender'
application-label-ky:'Xender'
application-label-my:'Xender'
application-label-az:'Xender'
application-label-uz:'Xender'
application-label-fr-CA:'Xender'
application-label-lo-LA:'Xender'
application-label-en-GB:'Xender'
application-label-bn-BD:'Xender'
application-label-et-EE:'Xender'
application-label-ka-GE:'Xender'
application-label-ky-KG:'Xender'
application-label-km-KH:'Xender'
application-label-zh-HK:'Xender'
application-label-si-LK:'Xender'
application-label-mk-MK:'Xender'
application-label-ur-PK:'Xender'
application-label-sq-AL:'Xender'
application-label-hy-AM:'Xender'
application-label-my-MM:'Xender'
application-label-zh-CN:'Xender'
application-label-pa-IN:'Xender'
application-label-ta-IN:'Xender'
application-label-te-IN:'Xender'
application-label-ml-IN:'Xender'
application-label-en-IN:'Xender'
application-label-kn-IN:'Xender'
application-label-mr-IN:'Xender'
application-label-or-IN:'Xender'
application-label-as-IN:'Xender'
application-label-gu-IN:'Xender'
application-label-mn-MN:'Xender'
application-label-ne-NP:'Xender'
application-label-pt-BR:'Xender'
application-label-gl-ES:'Xender'
application-label-eu-ES:'Xender'
application-label-is-IS:'Xender'
application-label-es-US:'Xender'
application-label-pt-PT:'Xender'
application-label-en-AU:'Xender'
application-label-zh-TW:'Xender'
application-label-es-MX:'Xender'
application-label-ms-MY:'Xender'
application-label-az-AZ:'Xender'
application-label-kk-KZ:'Xender'
application-label-uz-UZ:'Xender'
application-icon-160:'r/r/a.png'
application-icon-240:'r/r/a.png'
application-icon-320:'r/d/a.png'
application-icon-480:'r/c/a.png'
application-icon-640:'r/c/a.png'
application-icon-65535:'r/c/a.png'
application: label='Xender' icon='r/r/a.png'
launchable-activity: name='cn.xender.ui.activity.SplashActivity' label='Xender' icon=''
feature-group: label=''
uses-feature-not-required: name='android.hardware.audio.low_latency'
uses-feature-not-required: name='android.hardware.bluetooth'
uses-feature-not-required: name='android.hardware.camera'
uses-feature-not-required: name='android.hardware.camera.focus'
uses-feature-not-required: name='android.hardware.location'
uses-feature-not-required: name='android.hardware.location.gps'
uses-feature-not-required: name='android.hardware.location.network'
uses-feature-not-required: name='android.hardware.screen.portrait'
uses-feature-not-required: name='android.hardware.telephony'
uses-feature-not-required: name='android.hardware.touchscreen'
uses-feature-not-required: name='android.hardware.wifi'
main
other-activities
other-receivers
other-services
supports-screens: 'small' 'normal' 'large' 'xlarge'
supports-any-density: 'true'
locales: '--_--' 'ca' 'da' 'fa' 'ja' 'ka' 'pa' 'ta' 'nb' 'be' 'de' 'ne' 'te' 'af' 'bg' 'th' 'fi' 'hi' 'si' 'vi' 'kk' 'mk' 'sk' 'uk' 'el' 'gl' 'ml' 'nl' 'pl' 'sl' 'tl' 'am' 'km' 'bn' 'en' 'in' 'kn' 'mn' 'ko' 'lo' 'no' 'ro' 'sq' 'ar' 'fr' 'hr' 'mr' 'sr' 'tr' 'ur' 'bs' 'cs' 'es' 'is' 'ms' 'et' 'it' 'lt' 'pt' 'eu' 'gu' 'hu' 'ru' 'zu' 'lv' 'sv' 'iw' 'sw' 'hy' 'ky' 'my' 'az' 'uz' 'fr-CA' 'lo-LA' 'en-GB' 'bn-BD' 'et-EE' 'ka-GE' 'ky-KG' 'km-KH' 'zh-HK' 'si-LK' 'mk-MK' 'ur-PK' 'sq-AL' 'hy-AM' 'my-MM' 'zh-CN' 'pa-IN' 'ta-IN' 'te-IN' 'ml-IN' 'en-IN' 'kn-IN' 'mr-IN' 'or-IN' 'as-IN' 'gu-IN' 'mn-MN' 'ne-NP' 'pt-BR' 'gl-ES' 'eu-ES' 'is-IS' 'es-US' 'pt-PT' 'en-AU' 'zh-TW' 'es-MX' 'ms-MY' 'az-AZ' 'kk-KZ' 'uz-UZ'
densities: '160' '240' '320' '480' '640' '65535'


Output of -
./aapt dump badging my.apk | grep versionCode | awk '{print $3}' | sed s/versionCode=//g | sed s/\'//g


303

Answer

You don't need a bunch of post-processing, just this expression in grep. What i have done is use grep with PCRE capabilities, which is enabled with the -P flag.

$ ./aapt dump badging my.apk | grep -Po "versionCode=\'\K[^\s\']+" 
303

(or) save it in a bash variable as

$ VERSIONCODE="$(./aapt dump badging my.apk | grep -Po "versionCode=\'\K[^\s\']+")"
$ echo "$VERSIONCODE"
303

The -o flag in grep is to extract the versionCode string alone and with the regular expression,

  • \K to ignore in the search-result up-to that part of the string.
  • Rest of the expression to extract one (or) more number of characters within single quotes ''.

You can verify the regEx here.