|
| 1 | +#!/usr/bin/env python3 |
| 2 | +""" |
| 3 | +apk-size-analyzer.py -- Analyze APK structure and find what's making it bloated |
| 4 | +Shows: classes.dex size, resources, native libs, total breakdown by percentage |
| 5 | +Usage: python3 apk-size-analyzer.py app.apk |
| 6 | +""" |
| 7 | +import zipfile, sys, json |
| 8 | +from collections import defaultdict |
| 9 | + |
| 10 | +def analyze_apk(apk_path): |
| 11 | + try: |
| 12 | + z = zipfile.ZipFile(apk_path, 'r') |
| 13 | + except Exception as e: |
| 14 | + print(f"Error: {e}"); sys.exit(1) |
| 15 | + |
| 16 | + sizes = defaultdict(int) |
| 17 | + for info in z.infolist(): |
| 18 | + path = info.filename |
| 19 | + size = info.file_size |
| 20 | + |
| 21 | + if path.endswith('.dex'): |
| 22 | + sizes['dex'] += size |
| 23 | + elif path.startswith('lib/'): |
| 24 | + arch = path.split('/')[1] if len(path.split('/')) > 1 else 'unknown' |
| 25 | + sizes[f'lib_{arch}'] += size |
| 26 | + elif path.startswith('resources.arsc') or path.startswith('res/'): |
| 27 | + sizes['resources'] += size |
| 28 | + elif path.endswith('.so'): |
| 29 | + sizes['native'] += size |
| 30 | + elif path.startswith('assets/'): |
| 31 | + sizes['assets'] += size |
| 32 | + elif path == 'AndroidManifest.xml': |
| 33 | + sizes['manifest'] += size |
| 34 | + else: |
| 35 | + sizes['other'] += size |
| 36 | + |
| 37 | + total = sum(sizes.values()) |
| 38 | + print(f"\n📦 APK Size Analysis: {apk_path}") |
| 39 | + print(f"Total: {total / 1024 / 1024:.1f} MB\n") |
| 40 | + print(f"{'Component':<20} {'Size':<15} {'%':<8}") |
| 41 | + print("─" * 45) |
| 42 | + |
| 43 | + for key in sorted(sizes.keys(), key=lambda k: sizes[k], reverse=True): |
| 44 | + size = sizes[key] |
| 45 | + pct = (size / total * 100) if total > 0 else 0 |
| 46 | + size_str = f"{size / 1024 / 1024:.1f} MB" if size > 1024*1024 else f"{size / 1024:.0f} KB" |
| 47 | + print(f"{key:<20} {size_str:<15} {pct:>6.1f}%") |
| 48 | + |
| 49 | +if __name__ == "__main__": |
| 50 | + if len(sys.argv) < 2: |
| 51 | + print("Usage: python3 apk-size-analyzer.py <app.apk>") |
| 52 | + sys.exit(1) |
| 53 | + analyze_apk(sys.argv[1]) |
0 commit comments