From 17babf57dd737f1466b1d7a48b3d35b9a9b7a227 Mon Sep 17 00:00:00 2001 From: IronTony Date: Tue, 29 Sep 2026 16:59:14 -0400 Subject: [PATCH] fix(android): ship R8 keep rules for DocuSign's esign models DocuSign's androidsdk AAR ships consumer rules for com.docusign.androidsdk only. The Gson models in sdk-esign-api are named in generic signatures but never used directly, so R8 removes them. An app with minification on lost login and captive signing at runtime, with no crash at launch. android/consumer-rules.pro keeps com.docusign.esign.model.** and the module's class names, and consumerProguardFiles applies it in every consuming app. In an Expo SDK 57 app with enableMinifyInReleaseBuilds, the 2.0.0 release APK kept 0 of the 580 model classes. With the packed 2.0.1 the rule is in the merged R8 configuration, all 580 classes and ViewUrl.url survive, and the APK grows by 0.6 MB. --- CHANGELOG.md | 6 ++++++ README.md | 6 +++++- android/build.gradle | 1 + android/consumer-rules.pro | 8 ++++++++ package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 android/consumer-rules.pro diff --git a/CHANGELOG.md b/CHANGELOG.md index 82a6da2..f9f30b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 2.0.1 + +### Fixes + +- **Android**: the module ships R8 keep rules for the models in DocuSign's `sdk-esign-api`. DocuSign's own rules cover `com.docusign.androidsdk` only, so an app with minification on lost the fields Gson fills on those models, and login and captive signing failed at runtime without a crash at launch. The rules reach the app through `consumerProguardFiles`, so an app can delete any DocuSign keep rules it added itself. + ## 2.0.0 Upgrading from 1.x: every failure now rejects with a `DocuSignError`. Check any code that branches on `error.code`, matches message text, handles `status: 'error'` from `presentCaptiveSigning*`, or reads `errorCode` in an `addSigningErrorListener` callback. Codes are the lowercase codes the README documents, on both platforms, where iOS previously emitted `ERR_`-prefixed variants and Android rejected most failures as `signing_failed`. The new Android `launchStrategy` is opt-in. Both native SDKs also move forward, see [Native SDKs](#native-sdks) for what that changes in your app. diff --git a/README.md b/README.md index 33786f0..17237fb 100644 --- a/README.md +++ b/README.md @@ -114,11 +114,15 @@ The DocuSign native SDKs are **NOT bundled** inside this npm package. They are d DocuSign's `com.docusign:sdk-pdf:2.1.7` AAR ships a pre-generated `com.bumptech.glide.GeneratedAppGlideModuleImpl.class` that collides at dex time with any other Glide-based library in the host app (notably `expo-image`, `react-native-fast-image`, and similar). To avoid this without redistributing DocuSign's binary, the Expo Config Plugin downloads `sdk-pdf-2.1.7.aar` directly from DocuSign's public Maven during `expo prebuild`, verifies its SHA-256 against a pinned hash, removes the offending class from the AAR's `classes.jar` in-memory, and writes the stripped artifact to `node_modules/react-native-docusign/android/libs/`. The module's `android/build.gradle` references it by file path at consumer build time. The download is cached after the first run; corrupted or partial caches are detected and regenerated. SHA mismatch or fetch failure aborts `expo prebuild` with an actionable error rather than silently letting the Android build fail later at the dex step. +### Minified release builds (R8) + +Apps with `minifyEnabled` (for Expo, `expo-build-properties` `android.enableMinifyInReleaseBuilds`) need no DocuSign keep rules of their own from 2.0.1. The module's `android/consumer-rules.pro` reaches the app's R8 configuration through `consumerProguardFiles` and keeps `com.docusign.esign.model.**`, the Gson models in DocuSign's `sdk-esign-api` JAR. DocuSign's own rules cover `com.docusign.androidsdk` only, so without it R8 strips the model fields and login and captive signing fail at runtime. The module's class names are also kept, so `DocuSignError.native.domain` stays readable in an obfuscated build. + ### What ships inside this package - TypeScript source + type definitions - Swift + Kotlin bridge source files -- Podspec and gradle config +- Podspec, gradle config and R8 consumer rules - Config plugin compiled output - README, CHANGELOG, LICENSE diff --git a/android/build.gradle b/android/build.gradle index f75d55f..7bc557c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -42,6 +42,7 @@ android { targetSdkVersion safeExtGet("targetSdkVersion", 35) versionCode 1 versionName "1.0.5" + consumerProguardFiles 'consumer-rules.pro' } buildFeatures { diff --git a/android/consumer-rules.pro b/android/consumer-rules.pro new file mode 100644 index 0000000..00eacfe --- /dev/null +++ b/android/consumer-rules.pro @@ -0,0 +1,8 @@ +# Gson fills com.docusign.esign.model fields by reflection, and DocuSign's +# sdk-esign-api JAR ships no keep rules. Keeping the whole esign package +# fails R8 on the missing org.apache.oltu classes, so only the models. +-keep class com.docusign.esign.model.** { *; } + +# DocuSignError.native.domain carries the Android exception class name. +# Keeps this module's names readable when the app obfuscates. +-keepnames class expo.modules.docusign.** diff --git a/package-lock.json b/package-lock.json index 609594f..79841a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-native-docusign", - "version": "2.0.0", + "version": "2.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "react-native-docusign", - "version": "2.0.0", + "version": "2.0.1", "license": "MIT", "dependencies": { "adm-zip": "^0.6.1" diff --git a/package.json b/package.json index 7eac90a..285bc2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-docusign", - "version": "2.0.0", + "version": "2.0.1", "description": "React Native / Expo native module wrapping DocuSign iOS and Android SDKs for in-app captive signing", "main": "build/index.js", "types": "build/index.d.ts",