def extract_apk_icons(icon_filename, apk, apkzip, repo_dir):
- """
- Extracts icons from the given APK zip in various densities,
- saves them into given repo directory
- and stores their names in the APK metadata dictionary.
+ """Extracts PNG icons from an APK with the supported pixel densities
+
+ Extracts icons from the given APK zip in various densities, saves
+ them into given repo directory and stores their names in the APK
+ metadata dictionary. If the icon is an XML icon, then this tries
+ to find PNG icon that can replace it.
:param icon_filename: A string representing the icon's file name
:param apk: A populated dictionary containing APK metadata.
:param apkzip: An opened zipfile.ZipFile of the APK file
:param repo_dir: The directory of the APK's repository
:return: A list of icon densities that are missing
+
"""
+ res_name_re = re.compile(r'res/(drawable|mipmap)-(x*[hlm]dpi|anydpi).*/(.*)_[0-9]+dp.(png|xml)')
+ pngs = dict()
+ for f in apkzip.namelist():
+ m = res_name_re.match(f)
+ if m and m.group(4) == 'png':
+ density = screen_resolutions[m.group(2)]
+ pngs[m.group(3) + '/' + density] = m.group(0)
empty_densities = []
for density in screen_densities:
if density not in apk['icons_src']:
# Extract the icon files per density
if icon_src.endswith('.xml'):
- png = os.path.basename(icon_src)[:-4] + '.png'
- for f in apkzip.namelist():
- if f.endswith(png):
- m = re.match(r'res/(drawable|mipmap)-(x*[hlm]dpi).*/', f)
- if m and screen_resolutions[m.group(2)] == density:
- icon_src = f
+ m = res_name_re.match(icon_src)
+ if m:
+ name = pngs.get(m.group(3) + '/' + str(density))
+ if name:
+ icon_src = name
if icon_src.endswith('.xml'):
empty_densities.append(density)
continue