3.5 KiB
Android JNI regression checks
Issue #64 reported an
UnsatisfiedLinkError when Java delivered a Google authorization result.
NativeActivity opens the native library and calls ANativeActivity_onCreate,
but this does not register the library with ART's Java native-method lookup.
FlectarActivity must also call System.loadLibrary("flectar_mail_android")
in its static initializer, before any native callback can run.
References:
- Android JNI loading guidance
- NativeActivity library loading
- ART native-method lookup
- Android instrumentation tests
Offline and packaged-library checks
python3 scripts/test-android-jni.py
python3 scripts/test-pdf-packaging.py
python3 scripts/verify-android-native.py path/to/flectar-mail.apk
The offline tests require a C compiler (cc) and GNU readelf or
llvm-readelf. Set READELF to an NDK llvm-readelf path if needed.
APK verification checks the dynamic symbol table for the native entry point
and every Java callback, in every packaged ABI, after release stripping.
Both Android release workflows already invoke this verifier through
verify-android-apk.sh. Symbol checks alone cannot verify Java library loading.
Device JNI tests
Build and stage the release Rust library and PDFium with the normal test APK script, then run the instrumentation suite on a connected ARM64 test device:
./scripts/build-android-test-apk.sh
./platform/android/gradle/gradlew -p platform/android/gradle \
:app:connectedDebugAndroidTest
This installs a debug application and a separate test APK. Use a test device
or Android user profile without an existing Flectar installation signed by a
different key. The Rust library is still the stripped release library staged
by the build script. An emulator needs a matching native ABI staged under
target/android/gradle-jni, or a Google APIs image with ARM64 translation.
Both Android build workflows run these tests on the API 30 Google APIs x86_64
image, which supports ARM64 translation, and retain the instrumentation reports.
NativeCallbacksTest invokes all five native callbacks through the real
FlectarActivity class and packaged Rust library. It intentionally does not
load the library itself or launch the Activity. No Google account, network
access, OAuth registration, or mailbox data is needed. Removing the static
initializer must make the invocation tests fail with UnsatisfiedLinkError.
These tests verify linkage, not OAuth authorization semantics.
Sign-in acceptance check
On the reported Pixel/GrapheneOS configuration and a supported stock Android
device, use an APK whose signing certificate and package are registered for
Google authorization. Exercise successful sign-in, consent cancellation,
and an authorization failure. Check that a result reaches the app without
UnsatisfiedLinkError; cancellation/failure must leave the app usable.
Also background/resume the app and open/cancel the document picker, since
those callbacks use the same library-loading path.
Record the APK version, Android version and test results before closing #64. If Google authorization still fails, preserve the provider's error separately from JNI linkage failures; never include access tokens or mailbox data in logs.