# -*- coding: utf-8 -*- r'''验证 APK 里真的开了明文流量。 Android 的 usesCleartextTraffic 是编译进 binary manifest 的, 光看源码不算数 —— 万一构建脚本没把新清单打进去,源码改对了也没用。 所以直接解 APK 看里面的 AndroidManifest。 ''' from __future__ import annotations import re import sys import zipfile from pathlib import Path ROOT = Path(__file__).resolve().parent.parent def main() -> int: apk = ROOT / "dist" / "ykxmz-watch-2.1.2.apk" if not apk.is_file(): print(" ✗ 找不到 %s" % apk) return 1 print(" APK: %s(%d 字节)" % (apk.name, apk.stat().st_size)) with zipfile.ZipFile(apk) as z: blob = z.read("AndroidManifest.xml") # binary manifest 里字符串以 UTF-16LE 存在字符串池里 # 简单办法:直接在字节里找关键词 text = blob.decode("utf-16-le", "ignore") for key in ("usesCleartextTraffic", "uses-permission", "INTERNET", "com.lanremote.watch"): print(" 含 %-24s %s" % (key, "✓" if key in text else "")) ok = "usesCleartextTraffic" in text # 属性名在池里,但值(true)是 0xFFFFFFFF 的布尔,不好直接找; # 属性名出现就说明清单里有这条 print() print(" %s 清单里带 usesCleartextTraffic" % ("✅" if ok else "❌ 没有 —— Android 9+ 还是会拒绝 http://")) return 0 if ok else 1 if __name__ == "__main__": sys.exit(main())