Skip to content

feat(apk): APK Inspector — analyze APKs without installing + auto assetlinks check#36

Open
manjees wants to merge 1 commit into
mainfrom
feature/issue-32
Open

feat(apk): APK Inspector — analyze APKs without installing + auto assetlinks check#36
manjees wants to merge 1 commit into
mainfrom
feature/issue-32

Conversation

@manjees

@manjees manjees commented May 15, 2026

Copy link
Copy Markdown
Owner

Closes #32.

Summary

New sidebar screen that takes a local .apk, parses the manifest and signing certificates in-process, and (the headline value) cross-references every autoVerify https domain against the live assetlinks.json — answering "would this build verify on a real device?" without needing a device at all.

Why this matters: today the only way to know whether an APK will pass App Links verification is to install it and run `pm get-app-links` on a device. That breaks the CI / release-review workflow. This PR puts that check in front of you before the artifact even reaches a tester.

What's in

Dependency

  • `net.dongliu:apk-parser:2.6.10` (Apache 2.0, Maven Central, pure Java) — only added to `jvmMain`

Domain

  • `ApkAnalysisResult` + supporting models. Fingerprint match is a sealed result so the UI can render `FullMatch` / `PartialMatch` / `NoMatch` / `PackageNotDeclared` / `AssetLinksUnavailable` with distinct UX.
  • `collapseLinkDomains` merges per-filter declarations into one entry per host so the user sees the same list Android's verifier would consider, not raw filter dumps.

Infrastructure

  • `ApkAnalyzer` wraps apk-parser. SHA-256/SHA-1 are computed locally from raw cert bytes (the lib doesn't expose them directly), normalized to canonical `XX:XX:XX:...` form so comparison with `assetlinks.json` is trivial elsewhere.
  • Manifest XML walked with DOM. Handles all 5 component tags (activity / activity-alias / service / receiver / provider) and every `` variant (`path` / `pathPrefix` / `pathSuffix` / `pathPattern` / `pathAdvancedPattern` + scheme + host + mimeType).
  • Filters with no link-relevant data are dropped — boot-completed/sync/push declarations would otherwise dominate large APKs and bury the App Link entries.

UseCase

  • `AnalyzeApkAndValidateLinksUseCase` fans out to `assetlinks.json` validation in parallel for every autoVerify https domain, then per-domain compares APK fingerprints against the JSON's.

UI

  • New sidebar item APK (Android icon) — last entry before Settings
  • AWT `FileDialog` → native picker on macOS / Windows / Linux
  • Result cards (top-down): Package · Signing certs · App Links verification (headline) · All declared link domains · Intent filters (collapsible — big APKs have 50+)
  • AAB rejected up-front with explicit "use the universal/split APK" hint — silently failing on .aab would mislead users

Test plan

  • `./gradlew :composeApp:compileKotlinJvm` → BUILD SUCCESSFUL
  • `./gradlew :composeApp:jvmTest` → all green
  • Manual: pick a published APK with App Links (e.g. Twitter / Instagram / Slack downloaded from APKMirror) and confirm:
    • Package metadata + version + label
    • At least one signing cert with a real SHA-256
    • autoVerify domains listed under "App Links verification" with a colored status row
    • "All declared link domains" includes both autoVerify and custom-scheme entries
  • Manual: pick a debug APK from a local Android Studio build → expect mostly `PackageNotDeclared` (no production assetlinks.json hosts the debug fingerprint)
  • Manual: rename an .aab to .apk and try to load → expect rejected with the AAB hint (or load real .aab to confirm the extension check fires)
  • Manual: pick a non-APK file (.zip, .txt) → expect "Only .apk files are supported" error

Out of scope (follow-up)

  • AAB (App Bundle) support — protobuf-based parsing, different library
  • Drag-and-drop file target (right now only the Browse button works)
  • APK Signature Scheme v3 key rotation visibility (we surface every cert, but don't label which is the "current" rotation)
  • Linking from APK Inspector results into Verification Deep Dive (one-click "fire intent on device with this URI")

…etlinks check

Adds a new sidebar screen that takes a local .apk, parses the manifest and
signing certificates in-process, and (the headline value) cross-references every
autoVerify https domain against the live assetlinks.json — answering "would this
build verify on a real device?" without needing a device at all.

Domain
- ApkAnalysisResult / ApkInfo / ApkSignature / ApkIntentFilter / ApkLinkDomain /
  ApkPathPattern / ApkDomainVerification / ApkFingerprintMatch (sealed)
- collapseLinkDomains merges per-filter declarations into one entry per host so
  the user sees the same domain list Android's verifier would consider

Infrastructure
- net.dongliu:apk-parser 2.6.10 wraps APK + manifest binary XML decoding +
  signing block parsing. Uses getAllCertificateMetas() to union v1/v2/v3 schemes.
- Fingerprints are SHA-256-hashed locally from raw cert bytes (apk-parser doesn't
  expose them directly), then formatted as XX:XX:XX:... uppercase to match the
  canonical form assetlinks.json uses
- Manifest XML is walked via DOM (DocumentBuilder) — explicitly handles all 5
  component tags (activity, activity-alias, service, receiver, provider) and
  every <data> attribute variant (path/pathPrefix/pathSuffix/pathPattern/
  pathAdvancedPattern + scheme + host + mimeType)
- Filters with no link-relevant data (boot completed, sync, push) are dropped
  rather than cluttering the result panel

UseCase
- AnalyzeApkAndValidateLinksUseCase fans out to assetlinks for every autoVerify
  https domain in parallel, then per-domain matches the APK's SHA-256
  fingerprints against the JSON's. Result: FullMatch / PartialMatch /
  NoMatch / PackageNotDeclared / AssetLinksUnavailable

UI
- New sidebar item "APK" (Android icon) routes to ApkInspectorScreen
- AWT FileDialog for native picker on macOS / Windows / Linux
- Result cards: Package metadata, Signing certs, App Links verification (the
  headline section), All declared link domains, Intent filters (collapsible —
  large APKs can have 50+)
- AAB rejected up-front with a clear "use the universal/split APK" hint —
  silently failing on .aab would mislead users

Test plan documented in PR body. Closes #32.
@manjees manjees added enhancement New feature or request ui User interface and visual improvements labels May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request ui User interface and visual improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: APK 파일 직접 분석 — 설치 없이 매니페스트·지문·딥링크 검증

1 participant