use jni::errors::Error as JniError;
use jni::objects::JClass;
use jni::refs::Global;
use jni::{Env, JavaVM, jni_str};
use log::{error, warn};
use std::sync::{Arc, OnceLock};
pub static JAVA_VM: OnceLock<Arc<JavaVM>> = OnceLock::new();
static LINGXIA_WEBVIEW_CLASS: OnceLock<Global<JClass<'static>>> = OnceLock::new();
pub fn initialize_jni(vm: JavaVM) {
let _ = vm.attach_current_thread(|env| -> jni::errors::Result<()> {
match env.find_class(jni_str!("com/lingxia/webview/LingXiaWebView")) {
Ok(class) => match env.new_global_ref(class) {
Ok(global_ref) => {
let _ = LINGXIA_WEBVIEW_CLASS.set(global_ref);
}
Err(e) => {
error!("Failed to create global reference for LingXiaWebView class: {e}");
}
},
Err(e) => {
error!("Failed to find LingXiaWebView class during initialization: {e}");
}
}
Ok(())
});
let _ = JAVA_VM.set(Arc::new(vm));
}
pub fn with_env<T, E>(f: impl FnOnce(&mut Env) -> Result<T, E>) -> Result<T, E>
where
E: From<jni::errors::Error>,
{
let vm = JAVA_VM
.get()
.ok_or(jni::errors::Error::UninitializedJavaVM)?;
vm.attach_current_thread(|env| {
let result = f(env);
let has_pending_exception = env.exception_check();
if has_pending_exception {
env.exception_describe();
env.exception_clear();
warn!("Detected and cleared pending Java exception before detach");
if result.is_ok() {
return Err(E::from(JniError::JavaException));
}
}
result
})
}
pub(crate) fn get_lingxia_webview_class() -> Option<&'static Global<JClass<'static>>> {
LINGXIA_WEBVIEW_CLASS.get()
}