diff --git a/android/src/main/java/com/reactnativecompressor/NitroPromiseAdapter.java b/android/src/main/java/com/reactnativecompressor/NitroPromiseAdapter.java
new file mode 100644
index 0000000..8d149f3
--- /dev/null
+++ b/android/src/main/java/com/reactnativecompressor/NitroPromiseAdapter.java
@@ -0,0 +1,105 @@
+package com.reactnativecompressor;
+
+import com.facebook.react.bridge.Promise;
+import com.facebook.react.bridge.WritableMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import kotlin.Unit;
+import kotlin.jvm.functions.Function0;
+import kotlin.jvm.functions.Function1;
+
+/**
+ * Adapts the React Native bridge {@link Promise} to a Nitro
+ * {@link com.margelo.nitro.core.Promise} so the existing domain methods — which speak the bridge
+ * {@code Promise} contract ({@code resolve}/{@code reject}) — can drive a Nitro Promise unchanged.
+ *
+ *
{@code convert} maps the resolved bridge value to the Nitro result type {@code T};
+ * {@code onSettle} runs once on resolve/reject (used to unregister progress callbacks).
+ *
+ *
This is intentionally written in Java rather than Kotlin: the bridge {@code Promise} interface
+ * declares {@code code} as non-null ({@code String}) on some React Native versions and nullable
+ * ({@code String?}) on others. Kotlin override parameter types are invariant, so a single Kotlin
+ * source can only match one of those. Java erases nullability for override matching, so one Java
+ * implementation satisfies every React Native version.
+ */
+public class NitroPromiseAdapter implements Promise {
+ private final com.margelo.nitro.core.Promise promise;
+ private final Function1