1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
//! Abstractions for Rust access to Android state (native Java objects)
//! managed by UI toolkits.
//!
//! # Usage of this crate
//! This crate exists for two kinds of downstream users:
//! 1. The UI toolkit that exposes its key internal states that hold
//! the current Android activity being displayed and the Java VM / JNI environment.
//! Either the UI toolkit or the app itself should set these states on startup,
//! specifically using [`set_vm`] and [`set_activity_getter`] functions.
//! 2. The Rust platform feature crates that need to access the current activity
//! and JNI environment in order to interact with the Android platform.
//!
//! ## Supported UI toolkits
//! * Makepad: enable the `makepad` Cargo feature.
//! * Others coming soon! (in the meantime, see below)
//!
//! ## Usage of this crate for other UI toolkits
//! For any other UI toolkits not listed above, you don't need to enable any cargo features.
//! Instead, your application code must manually provide two key states:
//! * a reference to the current Android activity.
//! * a reference to the current Java VM instance (and JNI environment).
//!
//! This can be achieved by doing the following:
//! * Enable the `set` Cargo feature, and
//! * Provide an [ActivityGetterFn] callback by calling [`set_activity_getter()`].
//! * If the [ActivityGetterFn] cannot provide a low-level [`JNIEnv`] object,
//! the application must also call the [`set_vm()`] function.
//!
#[cfg_attr(feature = "makepad", path = "makepad.rs")]
#[cfg_attr(not(feature = "makepad"), path = "custom.rs")]
mod inner;
use std::sync::OnceLock;
// Re-export all types that downstream users might need to instantiate.
pub use jni::{JavaVM, JNIEnv, objects::JObject};
/// Re-exports of low-level pointer types from the `jni-sys` crate.
pub mod sys {
pub use jni::sys::{jobject, JNIEnv};
}
/// The Java VM instance.
#[allow(dead_code)]
static VM: OnceLock<JavaVM> = OnceLock::new();
/// Sets the current Java VM.
#[inline]
pub fn set_vm(vm: JavaVM) -> Result<(), JavaVM> {
VM.set(vm)
}
/// The function signature registered by the UI toolkit that provides pointers to
/// current JNI environment (optional) and the current activity (as a jobect).
pub type ActivityGetterFn = fn() -> (Option<*mut sys::JNIEnv>, sys::jobject);
/// The function registered by the UI toolkit that provides raw pointers
/// to the current Android Activity object and JNI environment.
#[allow(dead_code)]
static ACTIVITY_GETTER: OnceLock<ActivityGetterFn> = OnceLock::new();
/// Registers the function that retrieves pointers to the
/// current JNI environment (optional) and the current Android Activity (as a jobect).
///
/// ## Safety
/// The caller must ensure that the provided function `f` provides correct pointers
/// to the current JNI environment (if used) and the current Android Activity.
#[inline]
pub unsafe fn set_activity_getter(f: ActivityGetterFn) -> Result<(), ActivityGetterFn> {
ACTIVITY_GETTER.set(f)
}
/// Invokes the given closure `f` with the current JNI environment
/// and the current activity.
///
/// Returns `None` upon error, including:
/// * If the function that gets the current activity and JNI environment
/// has not been set.
/// * If the current JNI environment cannot be obtained.
pub fn with_activity<F, R>(f: F) -> Option<R>
where
F: for<'a, 'b, 'c, 'd> Fn(&'a mut JNIEnv<'b>, &'c JObject<'d>) -> R,
{
inner::with_activity_inner(f)
}