一键导入
r8-jni-keep-rules
R8 and ProGuard keep rules for serializable routes, JNI bindings, protobufs, and minification.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
R8 and ProGuard keep rules for serializable routes, JNI bindings, protobufs, and minification.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | r8-jni-keep-rules |
| description | R8 and ProGuard keep rules for serializable routes, JNI bindings, protobufs, and minification. |
Release builds minify the app via R8. Three failure modes are common:
System.loadLibrary can't resolve the JNI signature → runtime UnsatisfiedLinkError.kotlinx.serialization @Serializable class loses its generated $$serializer or companion, and Navigation Compose type-safe route encode/decode fails → runtime SerializationException on nav transition.The project keeps keep-rules narrow on purpose. Read the hard rule first:
Do not paste
missing_rules.txtsuggestions verbatim. Add the smallest rule that names the exact compatibility boundary. No blanket-keep class **or-dontwarn **— the reviewer will push back. —app/proguard-rules.pro:8-10
| File | Scope | Contains |
|---|---|---|
core/engine/consumer-rules.pro | JNI boundary for the native engine | RipDpiProxyNativeBindings, Tun2SocksNativeBindings, NetworkDiagnosticsNativeBindings — -keepclasseswithmembernames + native <methods>; only |
core/data/consumer-rules.pro | Proto-lite compatibility surface | com.poyka.ripdpi.proto.** keep |
app/proguard-rules.pro | App-level shims (intentionally tiny) | Only Guava j2objc -dontwarn today |
Rule: Engine/Data compatibility boundaries belong in module-level consumer rules, not in app/proguard-rules.pro. Reviewers reject app-level rules that could have lived in a consumer rule file.
When you add a class with external fun members called from Rust:
core/engine/consumer-rules.pro following the exact pattern of the three existing entries.-keepclasseswithmembernames + native <methods>; only. Do not add -keep class (full class preservation) — only the native method names need to survive shrinking, the higher-level Kotlin wrapper does not../gradlew :app:assembleRelease followed by launching the app and triggering a call into the new binding.Anchor example:
-keepclasseswithmembernames class com.poyka.ripdpi.core.RipDpiProxyNativeBindings {
native <methods>;
}
@Serializable navigation routeNavigation Compose type-safe routes use kotlinx.serialization at runtime. Read the active Navigation Compose version from gradle/libs.versions.toml, and locate ConfigGraph / SettingsGraph by symbol in app/src/main/kotlin/com/poyka/ripdpi/ui/navigation/RipDpiNavHost.kt. R8 can strip a generated $$serializer companion.
Current state: the project has no app-level -keep rule for serializable routes today. It works because the routes are data objects (stateless) and the Compose/Kotlin serialization Gradle plugin emits a consumer rule. Verify this remains true when adding a @Serializable data class route with fields.
If a future release build crashes with kotlinx.serialization.SerializationException: Serializer for class 'X' is not found:
-keepclassmembers class com.poyka.ripdpi.ui.navigation.<RouteName> {
kotlinx.serialization.KSerializer serializer(...);
<fields>;
}
-keep class com.poyka.ripdpi.ui.navigation.** { *; } — that defeats minification for the entire navigation graph.The existing rule -keep class com.poyka.ripdpi.proto.** { *; } covers everything under that package. If a new schema lands under a different package (e.g. a core/diagnostics-data proto), add a module-scoped consumer rule in that module's consumer-rules.pro, not a line in app/proguard-rules.pro.
missing_rules.txt after a failed release buildR8 emits app/build/outputs/mapping/release/missing_rules.txt with suggestions. These are mechanical — they don't know what's a genuine compatibility boundary vs. a false positive.
Review protocol:
consumer-rules.pro.Class.forName strings) rather than suppress.missing_rules.txt as-is, and never cat missing_rules.txt >> app/proguard-rules.pro.After any change to a .pro file:
./gradlew :app:assembleRelease — must complete without R8 warnings escalating to errors../gradlew staticAnalysis — lint must not regress.missing_rules.txt appears with new suggestions after your change, treat the appearance itself as a review signal: something in your diff created a new boundary that R8 can't analyze. Surface this in PR review, don't paper over it.-consumerProguardFiles from each library. Don't re-declare their rules.AndroidManifest.xml.-dontwarn com.google.j2objc.annotations.** in app/proguard-rules.pro.Run android skills r8 for Google's generic R8 skill; use it alongside this RIPDPI-specific skill for background on new R8 features, obfuscation dictionaries, or full-mode vs compat-mode semantics. This skill is the project-specific authority for what to keep and where; Google's skill explains why R8 behaves the way it does.
Use this skill to generate well-branded interfaces and assets for RIPDPI (an Android-native, Compose-first VPN and DPI-bypass app), either for production or throwaway prototypes/mocks/etc. Contains essential design guidelines, colors, type, fonts, brand-ship icons, and an interactive UI kit of every public composable from the live ui/components tree.
Use when managing the Rust workspace, adding/removing crates, editing workspace dependencies, running cargo nextest/audit/deny, configuring Cargo profiles for Android cross-compilation, debugging Cargo.lock churn, migrating crate edition, or wiring Gradle to cargo via the ripdpi.android.rust-native plugin.
Use when modifying the diagnostics scan pipeline, ScanRequest/ScanReport types, ProbeTask families, ripdpi-monitor-engine / ripdpi-diagnostics-* crates, strategy-probe candidates, the diagnostics catalog (packs/profiles), wire-schema contracts between Rust and Kotlin, DIAGNOSTICS_ENGINE_SCHEMA_VERSION, golden contract tests, or adding a new probe type / profile. Triggers on diagnostics scans, strategy probes, automatic audit, dpi-detector profiles, or anything in core/diagnostics or native/rust/crates/ripdpi-monitor-*.
Android-specific Rust build, verification, and packaging — per-target 16 KiB page alignment, size-optimized release profile, ELF symbol allowlist, .so size budgets, NDK 29 specifics. Use when modifying .cargo/config.toml for Android targets, the workspace [profile.release] / [profile.android-jni] block, or when verifying a built .so before release.
Telemetry and observability discipline for the RIPDPI Android Rust stack — control-plane vs data-plane logging, bounded flume event queues, atomic counters, snapshot polling, readiness callbacks, and deterministic JSON contracts. Use when authoring or modifying telemetry emission code, the bounded event ring, the Kotlin-side telemetry consumer, or any per-packet logging.
Custom detekt rules, DI/privacy/suppression guardrails, detekt.yml configuration, and false-positive triage.