use_androguard.show_path = True
+def _get_androguard_APK(apkfile):
+ try:
+ from androguard.core.bytecodes.apk import APK
+ except ImportError:
+ raise FDroidException("androguard library is not installed and aapt not present")
+
+ return APK(apkfile)
+
+
+def ensure_final_value(packageName, arsc, value):
+ """Ensure incoming value is always the value, not the resid
+
+ androguard will sometimes return the Android "resId" aka
+ Resource ID instead of the actual value. This checks whether
+ the value is actually a resId, then performs the Android
+ Resource lookup as needed.
+
+ """
+ if value:
+ returnValue = value
+ if value[0] == '@':
+ try: # can be a literal value or a resId
+ res_id = int('0x' + value[1:], 16)
+ res_id = arsc.get_id(packageName, res_id)[1]
+ returnValue = arsc.get_string(packageName, res_id)[1]
+ except ValueError:
+ pass
+ return returnValue
+
+
def is_apk_and_debuggable_aapt(apkfile):
p = SdkToolsPopen(['aapt', 'dump', 'xmltree', apkfile, 'AndroidManifest.xml'],
output=False)
def is_apk_and_debuggable_androguard(apkfile):
- try:
- from androguard.core.bytecodes.apk import APK
- except ImportError:
- raise FDroidException("androguard library is not installed and aapt not present")
-
- apkobject = APK(apkfile)
+ apkobject = _get_androguard_APK(apkfile)
if apkobject.is_valid_APK():
debuggable = apkobject.get_element("application", "debuggable")
if debuggable is not None:
return is_apk_and_debuggable_aapt(apkfile)
-def get_apk_id_aapt(apkfile):
+def get_apk_id(apkfile):
"""Extract identification information from APK using aapt.
:param apkfile: path to an APK file.
:returns: triplet (appid, version code, version name)
"""
+ if use_androguard():
+ return get_apk_id_androguard(apkfile)
+ else:
+ return get_apk_id_aapt(apkfile)
+
+
+def get_apk_id_androguard(apkfile):
+ if not os.path.exists(apkfile):
+ raise FDroidException(_("Reading packageName/versionCode/versionName failed, APK invalid: '{apkfilename}'")
+ .format(apkfilename=apkfile))
+ a = _get_androguard_APK(apkfile)
+ versionName = ensure_final_value(a.package, a.get_android_resources(), a.get_androidversion_name())
+ if not versionName:
+ versionName = '' # versionName is expected to always be a str
+ return a.package, a.get_androidversion_code(), versionName
+
+
+def get_apk_id_aapt(apkfile):
r = re.compile("^package: name='(?P<appid>.*)' versionCode='(?P<vercode>.*)' versionName='(?P<vername>.*?)'(?: platformBuildVersionName='.*')?")
p = SdkToolsPopen(['aapt', 'dump', 'badging', apkfile], output=False)
for line in p.output.splitlines():