diff --git a/README.md b/README.md
index c410e18..74c9cd0 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,36 @@ dotnet test Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Tests/
dotnet test Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.IntegrationTests/
```
+### Android DEX shrinking & obfuscation (R8)
+
+Release builds of the Android head run R8 over the Java/DEX side
+(`AndroidLinkTool=r8` in `Xamarin.Neo4j.Android.csproj`). Play Console's *DEX code
+optimization* report scores obfuscation at ~1% on a stock .NET MAUI build: .NET for
+Android runs no DEX shrinker by default, and even with R8 on, the ProGuard config the
+SDK generates hardcodes `-dontobfuscate` — a flag nothing later in the config list can
+undo. The `_AndroidObfuscateDex` target therefore drops that file from R8's `--pg-conf`
+list and substitutes `Xamarin.Neo4j.Android/proguard_xamarin.cfg` (the same file minus
+that line), plus a generated file carrying the `-printmapping`/`-keepattributes` tail
+the SDK would have appended. Measured on the Release APK: **49.8% of DEX classes
+renamed, up from ~0%**.
+
+Only library-internal classes are renamed: the trimmer emits a `-keep` rule for every
+Java type the managed bindings reference, aapt2 one for every class named in a layout
+or the manifest, and each Android Callable Wrapper gets its own.
+`Xamarin.Neo4j.Android/proguard.cfg` covers what those miss — things resolved by name
+from native code. Add to it if a Release build dies with `ClassNotFoundException`,
+`NoSuchFieldError` or `NoSuchMethodError` where a Debug build does not.
+
+`mapping.txt` is embedded in the AAB
+(`BUNDLE-METADATA/com.android.tools.build.obfuscation/proguard.map`), so Play Console
+retraces obfuscated Java stacks by itself. Managed (C#) stack traces are unaffected —
+R8 only touches DEX.
+
+Local Release builds must be clean: aapt2's keep rules are registered as a `FileWrite`,
+so an incremental build that skips the resource link has `IncrementalClean` delete them.
+The target caches a copy outside `FileWrites` and errors out if even that is missing —
+delete `Xamarin.Neo4j.Android/obj/Release` if it fires.
+
## Technology Stack
- .NET MAUI
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/Xamarin.Neo4j.Android.csproj b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/Xamarin.Neo4j.Android.csproj
index 4e87c99..7092d5f 100644
--- a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/Xamarin.Neo4j.Android.csproj
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/Xamarin.Neo4j.Android.csproj
@@ -53,4 +53,56 @@
+
+
+ r8
+
+
+
+
+
+
+
+
+
+ <_AndroidObfuscationProguardConfig>$(IntermediateOutputPath)proguard\proguard_obfuscate.cfg
+ <_AndroidAaptProguardRules>$(IntermediateOutputPath)proguard\aapt_rules.cached.txt
+
+
+ <_AndroidObfuscationProguardLines Include="-ignorewarnings" Condition="'$(AndroidR8IgnoreWarnings)' == 'True'" />
+ <_AndroidObfuscationProguardLines Include="-keepattributes SourceFile" />
+ <_AndroidObfuscationProguardLines Include="-keepattributes LineNumberTable" />
+
+ <_AndroidObfuscationProguardLines Include="-printmapping "$([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(AndroidProguardMappingFile)'))"" Condition="'$(AndroidProguardMappingFile)' != ''" />
+
+
+
+
+
+
+
+ <_ProguardConfiguration Remove="$(IntermediateOutputPath)proguard\proguard_xamarin.cfg" />
+ <_ProguardConfiguration Remove="$(IntermediateOutputPath)aapt_rules.txt" />
+ <_ProguardConfiguration Include="$(MSBuildProjectDirectory)\proguard_xamarin.cfg" />
+ <_ProguardConfiguration Include="$(_AndroidObfuscationProguardConfig)" />
+ <_ProguardConfiguration Include="$(_AndroidAaptProguardRules)" />
+
+
+
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/proguard.cfg b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/proguard.cfg
new file mode 100644
index 0000000..95bacd1
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/proguard.cfg
@@ -0,0 +1,22 @@
+# App-level R8 keep rules, on top of the ones .NET for Android generates
+# (see proguard_xamarin.cfg and the _AndroidObfuscateDex target in the csproj).
+
+# The .NET runtime resolves this one by name from native code -- no DEX
+# reference points at it, so R8 renames it and startup dies with
+# "ClassNotFoundException: net.dot.android.ApplicationRegistration".
+# The SDK's own config only covers net.dot.jni.** and net.dot.android.crypto.**,
+# because upstream never obfuscates.
+-keep class net.dot.android.** { *; (...); }
+
+# The trimmer's generated keep rules (proguard_project_references.cfg) cover the
+# Java *methods* the bindings call, but not their fields -- upstream never
+# obfuscates, so the gap never showed. A bound property backed by a Java field
+# reads it through JNI by name, and renaming breaks that:
+# NoSuchFieldError: no "Landroidx/lifecycle/Lifecycle$State;" field "DESTROYED"
+# NoSuchFieldError: no "I" field "left" in class "Landroidx/core/graphics/Insets;"
+# Only the API surface a binding can reach needs it; private fields still get
+# renamed, and class names -- what Play's report counts -- are untouched by this.
+-keepclassmembers class * {
+ public ;
+ protected ;
+}
diff --git a/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/proguard_xamarin.cfg b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/proguard_xamarin.cfg
new file mode 100644
index 0000000..14980b6
--- /dev/null
+++ b/Xamarin.Neo4j/Xamarin.Neo4j/Xamarin.Neo4j.Android/proguard_xamarin.cfg
@@ -0,0 +1,45 @@
+# Verbatim copy of the ProGuard configuration .NET for Android generates at
+# obj///proguard/proguard_xamarin.cfg, minus its hardcoded
+# "-dontobfuscate". ProGuard has no switch that undoes that flag, so the only
+# way to let R8 rename DEX classes is to drop the file that sets it from R8's
+# --pg-conf list and substitute this one (see the _AndroidObfuscateDex target
+# in the csproj).
+#
+# Taken from Microsoft.Android.Sdk 36.1.69 (.NET 10). When the Android SDK pack
+# is updated, diff this against the generated file after a Release build --
+# a keep rule added upstream and missed here means a runtime JNI failure.
+# The trailing -ignorewarnings/-keepattributes/-printmapping lines the SDK
+# appends to that file are regenerated by the csproj target instead.
+
+-keep class android.support.multidex.MultiDexApplication { (); }
+-keep class net.dot.jni.** { *; (); }
+-keep class mono.MonoRuntimeProvider* { *; (...); }
+-keep class mono.MonoPackageManager { *; (...); }
+-keep class mono.MonoPackageManager_Resources { *; (...); }
+-keep class mono.android.** { *; (...); }
+-keep class mono.java.** { *; (...); }
+-keep class mono.javax.** { *; (...); }
+-keep class net.dot.jni.ManagedPeer { *; (...); }
+-keep class xamarin.android.net.ServerCertificateCustomValidator_TrustManager { *; (...); }
+-keep class xamarin.android.net.ServerCertificateCustomValidator_TrustManager_FakeSSLSession { *; (...); }
+-keep class xamarin.android.net.ServerCertificateCustomValidator_AlwaysAcceptingHostnameVerifier { *; (...); }
+
+-keep class android.runtime.** { (...); }
+-keep class assembly_mono_android.android.runtime.** { (...); }
+# hash for android.runtime and assembly_mono_android.android.runtime.
+-keep class md52ce486a14f4bcd95899665e9d932190b.** { *; (...); }
+-keepclassmembers class md52ce486a14f4bcd95899665e9d932190b.** { *; (...); }
+
+# .NET runtime
+-keep class net.dot.android.crypto.** { *; (...); }
+
+# Android's template misses fluent setters...
+-keepclassmembers class * extends android.view.View {
+ *** set*(...);
+}
+
+# also misses those inflated custom layout stuff from xml...
+-keepclassmembers class * extends android.view.View {
+ (android.content.Context,android.util.AttributeSet);
+ (android.content.Context,android.util.AttributeSet,int);
+}