Lompat ke konten
dokumentasi.id
Commit 98ceeb4
v2
Star3,6 rb

12

Batasan Runtime dan Cakupan Hidden API

Jar kustom yang dihasilkan hiddenjar adalah alat kompilasi, bukan izin akses. Mengganti android.jar di SDK hanya membuat javac mau membaca signature @hide dan com.android.internal.*; perilaku aplikasi saat berjalan di device tidak berubah sama sekali. README menyatakan batas ini secara eksplisit: jar kustom hanya membuka kompilasi, sementara Android 9+ (API 28+) tetap menegakkan blocklist non-SDK untuk aplikasi non-system. README.md:99-100

Kompilasi Berhasil, Runtime Belum Tentu

Rantai di bawah memisahkan dua gerbang yang sering dianggap satu. Gerbang pertama adalah javac dan bisa dilewati dengan jar kustom. Gerbang kedua adalah ART di device dan tidak bisa dilewati oleh jar mana pun.

graph TD
  A["hiddenjar build"] --> B["android.jar kustom"]
  B --> C["javac: hidden API resolve"]
  C --> D["APK dipasang dan dijalankan"]
  D --> E{"API 28+ dan non-system app?"}
  E -->|ya| F["blocklist non-SDK menolak akses"]
  E -->|tidak| G["akses diizinkan"]
  F --> H["NoSuchMethodError / ClassNotFoundException"]
  style A fill:#f59e0b,color:#000
  style B fill:#8b5cf6,color:#fff
  style C fill:#2d7d46,color:#fff
  style D fill:#336791,color:#fff
  style E fill:#f59e0b,color:#000
  style F fill:#dc2626,color:#fff
  style G fill:#2d7d46,color:#fff
  style H fill:#dc2626,color:#fff
%% fig: Dua gerbang akses hidden API
%% desc: Jar kustom hanya meloloskan gerbang kompilasi; gerbang runtime tetap dijaga blocklist non-SDK pada API 28+.
Fig. 1: Dua gerbang akses hidden APIJar kustom hanya meloloskan gerbang kompilasi; gerbang runtime tetap dijaga blocklist non-SDK pada API 28+.

Blocklist Non-SDK Sejak API 28

Dokumentasi batasan menyebut konsekuensi konkretnya: kegagalan tidak muncul saat build, melainkan saat aplikasi berjalan. Ekspektasi yang wajar adalah NoSuchMethodError atau ClassNotFoundException kecuali aplikasi berstatus platform/system app atau API yang dipakai ada di greylist. Jar kustom tidak mengubah apa pun pada runtime. docs/BUILD_CUSTOM_ANDROID_JAR_FROM_EMULATOR.md:195-197

⚠️ Verifikasi empat tahap di cli/hiddenjar menguji javac dan integritas jar, bukan izin runtime. Jar yang lolos verifikasi tetap bisa gagal di device bila simbol yang dipanggil diblokir.

Kerapuhan Signature Antar Versi

Hidden API tidak dijamin kompatibel. Signature-nya berubah tanpa pemberitahuan, sehingga jar harus dibangun ulang per level API. docs/BUILD_CUSTOM_ANDROID_JAR_FROM_EMULATOR.md:198

Pengalaman pemakaian di repository ini mencatat kasus nyata: sejak jar kustom v28, sejumlah method tidak lagi dapat diakses dan Android Studio melaporkan formatShortElapsedTime has private access; workaround-nya adalah menyalin method tersebut ke kode sendiri. sample/src/main/java/com/anggrayudi/hiddenapi/sample/MainActivity.kt:44-52

GejalaPenyebabTindakan
NoSuchMethodError / ClassNotFoundException saat runtimeblocklist non-SDK pada API 28+jangan andalkan akses langsung; bungkus dengan fallback
formatShortElapsedTime has private access saat kompilasisignature berubah antar level APIsalin method ke kode sendiri
Kelas hilang setelah ganti level APIsignature hidden berubah tanpa jaminan kompatibilitasbangun ulang jar per level API

Kompromi --keep-bodies dan --keep-dangling

Secara default BuildJar menulis ulang setiap body method menjadi throw new RuntimeException("Stub!") dan mencetak peringatan bila mode itu dimatikan: [build] --keep-bodies: real method bodies kept; Gradle lint/unit tests will FAIL on this jar. cli/BuildJar.java:97-109 Alasannya teknis: body hasil dex2jar membawa blok try/catch, dan MockableJarGenerator milik Gradle — dipakai lint serta unit test — gagal dengan Cannot read field "outgoingEdges" because "handlerRangeBlock" is null (issue #46). Stub dibuat menyerupai android.jar bawaan SDK, dan karena javac hanya membaca signature, symbol hidden tetap resolve. cli/Stubifier.java:26-37

Sisi lain kompromi ini: body asli memang berguna untuk membaca source hasil decompile, tetapi MockableJarTransform akan menolak jar tersebut. docs/BUILD_CUSTOM_ANDROID_JAR_FROM_EMULATOR.md:199-206

Prune berjalan dengan logika yang sama. Overlay hanya mengambil tiga namespace, android/, com/android/internal/, dan dalvik/; kelas yang supertype-nya tidak lagi resolve dibuang agar graf jar tertutup seperti android.jar stok. cli/BuildJar.java:47-48 --keep-dangling melewati langkah itu dan mempertahankan kelas yatim, dengan risiko memunculkan kembali error issue #100 bila kelas tersebut dirujuk. docs/BUILD_CUSTOM_ANDROID_JAR_FROM_EMULATOR.md:207-210 CLI bahkan menggagalkan build bila jar membawa namespace yang menaungi JDK, bila jumlah kelasnya lebih sedikit dari jar SDK dasar, atau bila ada kelas publik dengan supertype tak terselesaikan. docs/BUILD_CUSTOM_ANDROID_JAR_FROM_EMULATOR.md:177-179

FlagEfekKonsekuensi
(default)body di-stub, kelas yatim dipangkaslint dan unit test menerima jar; body asli tidak bisa dibaca
--keep-bodiesbody dex2jar asli dipertahankanpesan: --keep-bodies: keeping real method bodies; Gradle lint/unit tests (MockableJarTransform) will FAIL on this jar
--keep-danglingkelas dengan supertype terfilter tetap adagraf supertype tidak tertutup; risiko error issue #100 saat dirujuk

Peringatan kedua flag dicetak ke stderr sebelum perakitan dimulai, sehingga kompromi yang dipilih terlihat di log build. cli/hiddenjar:325-326

Cakupan Sumber: Citra Emulator dan DEX yang Tersisa

Cakupan hidden API bergantung pada bytecode yang benar-benar ada di sumber. hiddenjar menolak jar yang tampak sebagai cangkang kosong: ambang MIN_JAR_BYTES=1024 dipakai bersama pemeriksaan classes[0-9]*\.dex, dan jar yang gagal salah satu syarat dilewati dengan pesan skip (stripped/no DEX, ...). cli/hiddenjar:19-19 cli/hiddenjar:296-301 Bila tidak ada satu pun jar yang punya DEX usable, proses berhenti dengan no framework jars had usable DEX — use an API >= 34 image or a device. cli/hiddenjar:313-313

Angka ukuran berikut menjelaskan mengapa citra lama tidak memadai — DEX-nya sudah dipindahkan ke boot image.

SumberAPIUkuran /system/framework/framework.jarIsi
Emulator google_apis, arm6424318 byteskosong, hanya META-INF/MANIFEST.MF
Emulator google_apis, arm6437≈48 MB5 DEX penuh
Ponsel fisik (Samsung A52)34≈51 MBpenuh

docs/BUILD_CUSTOM_ANDROID_JAR_FROM_EMULATOR.md:66-70

Pada citra API 37, konversi DEX menghasilkan 36.590 kelas, 6.295 di antaranya berada di bawah com/android/internal/. docs/BUILD_CUSTOM_ANDROID_JAR_FROM_EMULATOR.md:121 Jumlah itu adalah ukuran permukaan yang bisa dikompilasi, bukan ukuran permukaan yang bisa diakses saat runtime.

Untuk kebutuhan resource internal, jalur yang dipakai bukan akses langsung ke com.android.internal.R melainkan resolusi lewat nama, seperti yang dibahas di InternalAccessor: Membaca Resource com.android.internal dan ResourcesHolder dan Pengiriman via Broadcast.