Skip to content

Instantly share code, notes, and snippets.

@stuaxo
Created February 6, 2026 01:46
Show Gist options
  • Select an option

  • Save stuaxo/2c085fb82375da68c05496ad104b2a5b to your computer and use it in GitHub Desktop.

Select an option

Save stuaxo/2c085fb82375da68c05496ad104b2a5b to your computer and use it in GitHub Desktop.
Install apkm over adb
#!/usr/bin/env python3
# /// script
# requires-python = ">=3.8"
# ///
"""Advanced APKM Installer with Dry-Run and Namespace Awareness."""
import argparse
import re
import subprocess
import sys
import tempfile
import zipfile
from pathlib import Path
ARCH_SPLITS = {
"arm64-v8a": ["arm64_v8a", "arm64-v8a"],
"armeabi-v7a": ["armeabi_v7a", "armeabi-v7a"],
"x86_64": ["x86_64"],
"x86": ["x86"],
}
def run_adb(*args):
return subprocess.run(["adb", *args], capture_output=True, text=True)
def get_device_info():
abi = run_adb("shell", "getprop", "ro.product.cpu.abi").stdout.strip()
density = run_adb("shell", "getprop", "ro.sf.lcd_density").stdout.strip()
locale = run_adb("shell", "getprop", "persist.sys.locale").stdout.strip() or \
run_adb("shell", "getprop", "ro.product.locale").stdout.strip()
lang = locale.split('-')[0].split('_')[0].lower() if locale else "en"
return abi, density, lang
def density_to_split_name(density: str) -> str:
try: d = int(density)
except: return "mdpi"
if d <= 120: return "ldpi"
if d <= 160: return "mdpi"
if d <= 240: return "hdpi"
if d <= 320: return "xhdpi"
if d <= 480: return "xxhdpi"
return "xxxhdpi"
def get_apk_arch(apk_name: str) -> str or None:
name_lower = apk_name.lower()
for abi, markers in ARCH_SPLITS.items():
if any(m in name_lower for m in markers): return abi
return None
def evaluate_apk(apk_name: str, device_abi: str, device_density: str, device_lang: str):
"""Returns (bool: keep, str: reason)"""
name_lower = apk_name.lower()
# 1. Base/Master Logic
if "base" in name_lower or "master" in name_lower:
if not ("config" in name_lower or "split" in name_lower):
return True, "Core Component"
# 2. Arch Check
apk_arch = get_apk_arch(apk_name)
if apk_arch:
return (apk_arch == device_abi), f"Arch: {apk_arch}"
# 3. Density Check
density_markers = ["ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"]
for marker in density_markers:
if marker in name_lower:
target = density_to_split_name(device_density)
return (marker == target), f"Density: {marker}"
# 4. Language Check
lang_match = re.search(r'[\._]([a-z]{2})[\._]apk$', name_lower)
if lang_match:
apk_lang = lang_match.group(1)
keep = (apk_lang == device_lang or apk_lang == "en")
return keep, f"Lang: {apk_lang}"
return True, "Feature/Other"
def install_apkm(apkm_path: Path, install_all: bool = False, dry_run: bool = False) -> bool:
if not apkm_path.exists():
print(f"Error: {apkm_path} not found.")
return False
abi, density, lang = get_device_info()
print(f"\n--- Processing: {apkm_path.name} ---")
print(f"Device Profile: {abi} | {density}dpi | Lang: {lang}\n")
with tempfile.TemporaryDirectory() as tmp:
tmp_path = Path(tmp)
try:
with zipfile.ZipFile(apkm_path, "r") as zf:
zf.extractall(tmp_path)
except: return False
all_apks = sorted(list(tmp_path.rglob("*.apk")),
key=lambda x: ("base" in x.name.lower() or "master" in x.name.lower()),
reverse=True)
selected = []
print(f"{'STATUS':<10} | {'REASON':<15} | {'FILENAME'}")
print("-" * 60)
for apk in all_apks:
keep, reason = evaluate_apk(apk.name, abi, density, lang)
if install_all: keep, reason = True, "Force All"
status = "KEEP" if keep else "SKIP"
print(f"{status:<10} | {reason:<15} | {apk.name}")
if keep: selected.append(str(apk))
if dry_run:
print(f"\n[Dry Run] Would install {len(selected)} APKs.")
return True
if not selected:
print("\nNo compatible APKs found.")
return False
print(f"\nInstalling {len(selected)} splits via ADB...")
res = run_adb("install-multiple", "-r", *selected)
if res.returncode == 0:
print("✓ Installation Successful")
return True
else:
print(f"✗ ADB Error: {res.stderr}")
return False
def main():
parser = argparse.ArgumentParser(description="Namespace-Aware APKM Installer")
parser.add_argument("files", nargs="+", help="APKM files")
parser.add_argument("--all", action="store_true", help="Install all splits")
parser.add_argument("--dry-run", action="store_true", help="Preview selections without installing")
args = parser.parse_args()
for f in args.files:
install_apkm(Path(f), args.all, args.dry_run)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment