Skip to content

android: jni 0.22 update, exception checks, support any 'Context'#111

Merged
amodm merged 2 commits intoamodm:mainfrom
rib:rib/pr/android-jni-0.22-update
Mar 9, 2026
Merged

android: jni 0.22 update, exception checks, support any 'Context'#111
amodm merged 2 commits intoamodm:mainfrom
rib:rib/pr/android-jni-0.22-update

Conversation

@rib
Copy link
Copy Markdown
Contributor

@rib rib commented Mar 5, 2026

This addresses some exception-handling hygiene issues in the Android backend, and adds support for non-Activity Context references (considering that ndk-context does not guarantee that it provides an Activity reference).

With the previous implementation, if any of the JNI calls failed (such as the find_class call), that would have thrown an exception which was not automatically caught by the jni 0.21 crate. Since there was no code to ensure exceptions were checked and cleared on failure then the previous implementation would have had the side effect of blocking any further JNI on the same thread until the exception was cleared - but it would not have reported a recognisable error for indicating this side effect.

By contrast, with jni 0.22 we can rely on the attach_current_thread call to check and clear exceptions from the closure before returning.

This change also prepares this crate for a planned change in android-activity to initialize ndk-context with an Application reference instead of an Activity reference, ref: rust-mobile/android-activity#228

The fact that android-activity currently initializes ndk-context with an Activity reference is not itself guaranteed by the ndk-context crate (it only promises an android.content.Context reference) but the previous android backend was depending on receiving an Activity reference and would throw an exception if it didn't.

Note: Associating ndk-context with an Activity does not align well with Android application programming model because Android applications may often manage many Activities and it doesn't align with the design of ndk-context because the ndk-context state can't be re-initialized. Even if ndk-context could be changed to support state updates without a panic it could still be ambiguous to maintain a single global reference to one Activity in an application with multiple or possibly no Activity.

The new implementation will continue as it did before in case it does receive an Activity reference, but in case it receives some other kind of Context then now adds a ACTIVITY_NEW_TASK flag to the Intent to indicate that the new Activity is allowed to create a new Task. In practice this expected to be irrelevant (and result in identical behaviour) because the URL is most likely to be handled by a separate browser application.

This needed to bump the rust-version to 1.85 since that's the MSRV for jni 0.22

This also updates the Android test to be based on android-activity instead of ndk-glue

For reference, I've tested this with an updated na-egui example on Android which lets you interactively click links that are opened with this crate. I've tested with and without the planned android-activity change to initialize ndk-context with an Application reference instead of an Activity and have found the behaviour to be the same in either case.

This addresses some exception-handling hygiene issues in the Android
backend, and adds support for non-`Activity` `Context` references
(considering that `ndk-context` does not guarantee that it provides an
`Activity` reference).

With the previous implementation, if any of the JNI calls failed (such
as the `find_class` call), that would have thrown an exception which was
not automatically caught by the jni 0.21 crate. Since there was no code
to ensure exceptions were checked and cleared on failure then the
previous implementation would have had the side effect of blocking any
further JNI on the same thread until the exception was cleared - but it
would not have reported a recognisable error for indicating this side
effect.

By contrast, with jni 0.22 we can rely on the `attach_current_thread`
call to check and clear exceptions from the closure before returning.

This change also prepares this crate for a planned change in
`android-activity` to initialize `ndk-context` with an `Application`
reference instead of an `Activity` reference, ref:
rust-mobile/android-activity#228

The fact that `android-activity` currently initializes `ndk-context`
with an `Activity` reference is not itself guaranteed by the
`ndk-context` crate (it only promises an `android.content.Context`
reference) but the previous android backend was depending on receiving
an `Activity` reference and would throw an exception if it didn't.

Note: Associating `ndk-context` with an `Activity` does not align well
with Android application programming model because Android applications
may often manage many Activities and it doesn't align with the design of
`ndk-context` because the `ndk-context` state can't be re-initialized.
Even if ndk-context could be changed to support state updates without a
panic it could still be ambiguous to maintain a single global reference
to one Activity in an application with multiple or possibly no Activity.

The new implementation will continue as it did before in case it does
receive an Activity reference, but in case it receives some other kind
of `Context` then now adds a `ACTIVITY_NEW_TASK` flag to the `Intent` to
indicate that the new Activity is allowed to create a new `Task`. In
practice this expected to be irrelevant (and result in identical
behaviour) because the URL is most likely to be handled by a separate
browser application.

This needed to bump the rust-version to 1.85 since that's the MSRV for
jni 0.22

This also updates the Android test to be based on android-activity
instead of ndk-glue
@rib
Copy link
Copy Markdown
Contributor Author

rib commented Mar 5, 2026

Considering that the CI errors are related to the MSRV bump that introduces new Clippy lints, would you rather see the rust-version update in a separate PR that can be merged before this, or is it fine to look at fixing those lints in this PR too?

@amodm
Copy link
Copy Markdown
Owner

amodm commented Mar 6, 2026

Considering that the CI errors are related to the MSRV bump that introduces new Clippy lints, would you rather see the rust-version update in a separate PR that can be merged before this, or is it fine to look at fixing those lints in this PR too?

@rib it's ok to include it as part of this PR.

@amodm
Copy link
Copy Markdown
Owner

amodm commented Mar 9, 2026

@rib if you can enable Allow edits from maintainers for this PR, I can push a fix for the lints. Or you can do it yourself.

Never mind, saw that it was enabled already.

@amodm amodm merged commit 9085404 into amodm:main Mar 9, 2026
10 checks passed
@amodm
Copy link
Copy Markdown
Owner

amodm commented Mar 9, 2026

@rib this is now released as v1.2.0

@rib
Copy link
Copy Markdown
Contributor Author

rib commented Mar 9, 2026

Thanks, I was away this weekend so thanks for fixing up the CI issues with the MSRV bump and releasing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants