use jni::sys::jobject; use ndk_context::AndroidContext; use std::sync::Arc; pub use jni::Executor; pub use jni::{ errors::Result as JResult, objects::{JIntArray, JObject, JObjectArray, JString}, JNIEnv, JavaVM, }; pub fn get_context() -> AndroidContext { ndk_context::android_context() } pub fn with_attached(context: AndroidContext, closure: F) -> JResult where for<'j> F: FnOnce(&mut JNIEnv<'j>, JObject<'j>) -> JResult, { let vm = Arc::new(unsafe { JavaVM::from_raw(context.vm().cast())? }); let context = context.context(); let context = unsafe { JObject::from_raw(context as jobject) }; Executor::new(vm).with_attached(|env| closure(env, context)) } pub fn call_method_no_args_ret_int_array<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, method: &str, ) -> JResult> { let array: JIntArray = env.call_method(subject, method, "()[I", &[])?.l()?.into(); let length = env.get_array_length(&array)?; let mut values = Vec::with_capacity(length as usize); env.get_int_array_region(array, 0, values.as_mut())?; Ok(values) } pub fn call_method_no_args_ret_int<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, method: &str, ) -> JResult { env.call_method(subject, method, "()I", &[])?.i() } pub fn call_method_no_args_ret_bool<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, method: &str, ) -> JResult { env.call_method(subject, method, "()Z", &[])?.z() } pub fn call_method_no_args_ret_string<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, method: &str, ) -> JResult> { Ok(env .call_method(subject, method, "()Ljava/lang/String;", &[])? .l()? .into()) } pub fn call_method_no_args_ret_char_sequence<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, method: &str, ) -> JResult> { let cseq = env .call_method(subject, method, "()Ljava/lang/CharSequence;", &[])? .l()?; Ok(env .call_method(&cseq, "toString", "()Ljava/lang/String;", &[])? .l()? .into()) } pub fn call_method_string_arg_ret_bool<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, name: &str, arg: impl AsRef, ) -> JResult { env.call_method( subject, name, "(Ljava/lang/String;)Z", &[(&env.new_string(arg)?).into()], )? .z() } pub fn call_method_string_arg_ret_string<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, name: &str, arg: impl AsRef, ) -> JResult> { Ok(env .call_method( subject, name, "(Ljava/lang/String;)Ljava/lang/String;", &[(&env.new_string(arg)?).into()], )? .l()? .into()) } pub fn call_method_string_arg_ret_object<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, method: &str, arg: &str, ) -> JResult> { env.call_method( subject, method, "(Ljava/lang/String;)Ljava/lang/Object;", &[(&env.new_string(arg)?).into()], )? .l() } pub fn get_package_manager<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, ) -> JResult> { env.call_method( subject, "getPackageManager", "()Landroid/content/pm/PackageManager;", &[], )? .l() } pub fn has_system_feature<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, name: &str, ) -> JResult { call_method_string_arg_ret_bool(env, subject, "hasSystemFeature", name) } pub fn get_system_service<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, name: &str, ) -> JResult> { call_method_string_arg_ret_object(env, subject, "getSystemService", name) } pub fn get_property<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, name: &str, ) -> JResult> { call_method_string_arg_ret_string(env, subject, "getProperty", name) } pub fn get_devices<'j>( env: &mut JNIEnv<'j>, subject: &JObject<'j>, flags: i32, ) -> JResult> { env.call_method( subject, "getDevices", "(I)[Landroid/media/AudioDeviceInfo;", &[flags.into()], )? .l() .map(From::from) }