droid_wrap_utils/
lib.rs

1/*
2 * Copyright (c) 2024. The RigelA open source project team and
3 * its contributors reserve all rights.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and limitations under the License.
12 */
13
14mod error;
15
16pub use error::*;
17
18pub use jni::{
19    AttachGuard, JNIEnv, JavaVM, NativeMethod,
20    errors::Error as JniError,
21    objects::{
22        GlobalRef, JBooleanArray, JByteArray, JClass, JObject, JObjectArray, JString, JValueGen,
23        ReleaseMode,
24    },
25    sys::{jboolean, jbyte, jchar, jdouble, jfloat, jint, jlong, jshort, jsize},
26};
27use log::{debug, error, warn};
28use parking_lot::ReentrantMutex;
29use std::{
30    cell::RefCell,
31    collections::HashMap,
32    fmt::Debug,
33    hash::{DefaultHasher, Hash, Hasher},
34    str::FromStr,
35    sync::{Arc, LazyLock, OnceLock},
36};
37
38// Rust 代理对象的哈希值映射到 Rust 函数
39static HOOK_OBJECTS: LazyLock<
40    ReentrantMutex<
41        RefCell<
42            HashMap<
43                i32,
44                Arc<
45                    dyn Fn(&mut JNIEnv<'_>, &JObject<'_>, &JObjectArray<'_>) -> Result<GlobalRef>
46                        + Send
47                        + Sync,
48                >,
49            >,
50        >,
51    >,
52> = LazyLock::new(|| ReentrantMutex::new(RefCell::new(HashMap::new())));
53// Rust 代理对象的哈希值映射到 Java 被代理的对象的哈希值
54static HOOK_OBJECTS_OTHER: LazyLock<ReentrantMutex<RefCell<HashMap<u64, i32>>>> =
55    LazyLock::new(|| ReentrantMutex::new(RefCell::new(HashMap::new())));
56
57/**
58导出所有的pub条目。
59这还将定义必要的trait,以便于在本地为任何数据类型实现JAVA对象所需的功能。
60*/
61#[macro_export]
62macro_rules! import {
63    () => {
64        use std::{
65            rc::Rc,
66            sync::{Arc, Mutex},
67        };
68        pub use $crate::Result;
69        use $crate::{
70            GlobalRef, JObject, impl_array, null_value, to_java_byte_array, to_java_object_array,
71            unbind_proxy_handler, vm_attach,
72        };
73
74        /**
75        JObjectRef trait提供从任何数据类型获取java对象的全局引用。
76        rust使用Arc管理,无须手动释放java的全局引用。
77        */
78        pub trait JObjRef {
79            /**
80            获取java对象引用。
81            */
82            fn java_ref(&self) -> Result<GlobalRef>;
83        }
84
85        /**
86        用于从java对象创建本地对象。
87        */
88        pub trait JObjNew {
89            /// 字段类型
90            type Fields: Default;
91
92            /**
93            从java对象创建本地对象。
94            `this` java对象引用。
95            */
96            fn _new(this: &GlobalRef, fields: Self::Fields) -> Result<Self>
97            where
98                Self: Sized;
99
100            /**
101            创建空对象。
102            */
103            fn null() -> Result<Self>
104            where
105                Self: Sized,
106                Self::Fields: Default,
107            {
108                let mut env = vm_attach()?;
109                Self::_new(null_value(&mut env)?.as_ref(), Default::default())
110            }
111        }
112
113        /**
114        用于描述java类的信息。
115        */
116        pub trait JType: JObjRef + JObjNew {
117            /// java类的名称。
118            const CLASS: &'static str;
119
120            /// 对象的签名描述。
121            const OBJECT_SIG: &'static str;
122
123            /// 数组维度,0表示不是数组
124            const DIM: u8 = 0;
125        }
126
127        /**
128        用于Java动态代理的创建和删除。
129        */
130        pub trait JProxy: JObjNew + JObjRef {
131            /**
132            创建一个代理对象。
133            `fields` 传递给struct的自定义字段。
134            */
135            fn new(fields: Self::Fields) -> Result<Arc<Self>>;
136
137            /**
138            释放代理对象,解除绑定的handler。
139            */
140            fn release(&self) -> () {
141                if let Ok(ref r) = self.java_ref() {
142                    unbind_proxy_handler(r)
143                }
144            }
145        }
146
147        impl<T: JObjRef> JObjRef for &T {
148            fn java_ref(&self) -> Result<GlobalRef> {
149                self.java_ref()
150            }
151        }
152
153        impl<T: JObjNew> JObjNew for &T {
154            type Fields = T::Fields;
155
156            fn _new(this: &GlobalRef, fields: Self::Fields) -> Result<Self> {
157                panic!("Reference types cannot be constructed.")
158            }
159        }
160
161        impl<T: JObjRef + JObjNew> JObjRef for Option<T>
162        where
163            <T as JObjNew>::Fields: Default,
164        {
165            fn java_ref(&self) -> Result<GlobalRef> {
166                match self {
167                    None => T::null()?.java_ref(),
168                    Some(v) => v.java_ref(),
169                }
170            }
171        }
172
173        impl<T: JObjRef + JObjNew> JObjNew for Option<T> {
174            type Fields = T::Fields;
175
176            fn _new(this: &GlobalRef, fields: Self::Fields) -> Result<Self> {
177                Ok(match this.is_null() {
178                    true => None,
179                    false => T::_new(this, fields).ok(),
180                })
181            }
182        }
183
184        impl<T: JType> JType for Arc<T> {
185            const CLASS: &'static str = T::CLASS;
186            const OBJECT_SIG: &'static str = T::OBJECT_SIG;
187        }
188
189        impl<T: JObjRef> JObjRef for Arc<T> {
190            fn java_ref(&self) -> Result<GlobalRef> {
191                self.as_ref().java_ref()
192            }
193        }
194
195        impl<T: JObjNew> JObjNew for Arc<T> {
196            type Fields = T::Fields;
197
198            fn _new(this: &GlobalRef, fields: Self::Fields) -> Result<Self> {
199                Ok(T::_new(this, fields)?.into())
200            }
201        }
202
203        impl<T: JType> JType for Rc<T> {
204            const CLASS: &'static str = T::CLASS;
205            const OBJECT_SIG: &'static str = T::OBJECT_SIG;
206        }
207
208        impl<T: JObjRef> JObjRef for Rc<T> {
209            fn java_ref(&self) -> Result<GlobalRef> {
210                self.as_ref().java_ref()
211            }
212        }
213
214        impl<T: JObjNew> JObjNew for Rc<T> {
215            type Fields = T::Fields;
216
217            fn _new(this: &GlobalRef, fields: Self::Fields) -> Result<Self> {
218                Ok(T::_new(this, fields)?.into())
219            }
220        }
221
222        impl<T: JType> JType for Mutex<T> {
223            const CLASS: &'static str = T::CLASS;
224            const OBJECT_SIG: &'static str = T::OBJECT_SIG;
225        }
226
227        impl<T: JObjNew> JObjNew for Mutex<T> {
228            type Fields = T::Fields;
229
230            fn _new(this: &GlobalRef, fields: Self::Fields) -> Result<Self> {
231                Ok(T::_new(this, fields)?.into())
232            }
233        }
234
235        impl<T: JObjRef> JObjRef for Mutex<T> {
236            fn java_ref(&self) -> Result<GlobalRef> {
237                self.java_ref()
238            }
239        }
240
241        impl_array!(u8, 1);
242        impl_array!(String, 1);
243    };
244}
245
246/// 实现rust数组类型与java数组的自动关联
247///
248/// # 示例
249/// ```
250/// use droid_wrap_utils::impl_array;
251/// // 实现一维数组的关联
252/// impl_array!(String, 1);
253/// ```
254#[macro_export]
255macro_rules! impl_array {
256    (String, $dim: expr) => {
257        impl JObjNew for &[String] {
258            type Fields = ();
259
260            fn _new(this: &GlobalRef, fields: Self::Fields) -> Result<Self> {
261                Ok(&[])
262            }
263        }
264
265        impl JObjRef for &[String] {
266            fn java_ref(&self) -> Result<GlobalRef> {
267                let mut env = vm_attach()?;
268                let arr = self
269                    .iter()
270                    .filter_map(|i| env.new_string(i).ok())
271                    .collect::<Vec<_>>();
272                let sig = if Self::DIM <= 1 {
273                    Self::CLASS.to_string()
274                } else {
275                    "[".repeat((Self::DIM - 1) as _) + Self::OBJECT_SIG
276                };
277                let arr = to_java_object_array(&mut env, &arr, &sig)?;
278                Ok(env.new_global_ref(&arr)?)
279            }
280        }
281
282        impl JType for &[String] {
283            const CLASS: &'static str = <String as JType>::CLASS;
284            const OBJECT_SIG: &'static str = <String as JType>::OBJECT_SIG;
285            const DIM: u8 = $dim;
286        }
287
288        // 为 String 类型实现必要的 trait
289        impl JType for String {
290            const CLASS: &'static str = "java/lang/String";
291            const OBJECT_SIG: &'static str = "Ljava/lang/String;";
292        }
293
294        impl JObjRef for String {
295            fn java_ref(&self) -> Result<GlobalRef> {
296                let mut env = vm_attach()?;
297                let jstring = env.new_string(self)?;
298                Ok(env.new_global_ref(&jstring)?)
299            }
300        }
301
302        impl JObjNew for String {
303            type Fields = ();
304
305            fn _new(this: &GlobalRef, _fields: Self::Fields) -> Result<Self> {
306                if this.is_null() {
307                    return Ok(String::new());
308                }
309
310                let mut env = vm_attach()?;
311                let jstring = this.as_obj();
312                let java_string = env.get_string(jstring.into())?;
313                Ok(java_string.to_str()?.to_string())
314            }
315        }
316    };
317
318    (u8, $dim:expr) => {
319        impl JObjNew for &[u8] {
320            type Fields = ();
321
322            fn _new(this: &GlobalRef, fields: Self::Fields) -> Result<Self> {
323                Ok(&[])
324            }
325        }
326
327        impl JObjRef for &[u8] {
328            fn java_ref(&self) -> Result<GlobalRef> {
329                let mut env = vm_attach()?;
330                let arr = self.iter().map(|i| *i as _).collect::<Vec<_>>();
331                let arr = to_java_byte_array(&mut env, &arr)?;
332                Ok(env.new_global_ref(&arr)?)
333            }
334        }
335
336        impl JType for &[u8] {
337            const CLASS: &'static str = "B";
338            const OBJECT_SIG: &'static str = "B";
339            const DIM: u8 = $dim;
340        }
341    };
342}
343
344/**
345获取android系统的java虚拟机。
346*/
347pub fn android_vm<'a>() -> Result<&'static JavaVM> {
348    static JAVA_VM: LazyLock<Result<JavaVM>> = LazyLock::new(|| {
349        let ctx = ndk_context::android_context();
350        let vm = unsafe { JavaVM::from_raw(ctx.vm().cast()) }?;
351        Ok(vm)
352    });
353    JAVA_VM.as_ref().map_err(|e| e.to_owned())
354}
355
356/// 获取vm,将vm附加到当前线程,随后操作java虚拟机。
357///
358/// # 示例
359///
360/// ```
361/// use droid_wrap_utils::{vm_attach, Result};
362/// fn main() -> Result<()> {
363/// let mut env = vm_attach()?;
364/// let class = env.find_class("java/lang/String");
365/// dbg!(class)
366/// }
367/// ```
368#[inline(always)]
369pub fn vm_attach<'a>() -> Result<AttachGuard<'a>> {
370    let vm = android_vm()?;
371    vm.attach_current_thread().map_err(|e| e.into())
372}
373
374/**
375获取安卓的Context对象,这通常是NativeActivity对象的引用。
376*/
377pub fn android_context<'a>() -> JObject<'a> {
378    let ctx = ndk_context::android_context();
379    unsafe { JObject::from_raw(ctx.context().cast()) }
380}
381
382
383/**
384加载一个java类。
385*/
386pub fn load_class<'a>(class_name: &str) -> Result<JClass<'a>> {
387    let mut env = vm_attach()?;
388    let activity = android_context();
389    let class_loader = env.call_method(
390        activity,
391        "getClassLoader",
392        "()Ljava/lang/ClassLoader;",
393        &[],
394    )?;
395    let cls_name = env.new_string(class_name)?;
396    let loaded_class = env.call_method(
397        class_loader.l()?,
398        "loadClass",
399        "(Ljava/lang/String;)Ljava/lang/Class;",
400        &[(&cls_name).into()],
401    )?;
402    Ok(loaded_class.l()?.into())
403}
404
405/// 创建一个java动态代理,用于在rust层实现java接口的方法。
406///
407/// # Arguments
408///
409/// * `interfaces`: 要实现的java接口。
410/// * `handler`: 代理的处理函数。
411///
412/// 返回: `Result<GlobalRef>` 代理对象
413///
414/// # 示例
415///
416/// ```
417/// use droid_wrap_utils::new_proxy;
418/// let proxy = new_proxy(&["java.lang.Runnable"]);
419/// ```
420//noinspection SpellCheckingInspection
421pub fn new_proxy(interfaces: &[&str]) -> Result<GlobalRef> {
422    let class = load_rust_call_method_hook_class()?;
423    let mut env = vm_attach()?;
424    let obj = env.new_object(class, "()V", &[])?;
425    let faces = env.new_object_array(
426        interfaces.len() as jsize,
427        "java/lang/Class",
428        &JObject::null(),
429    )?;
430    for i in 0..interfaces.len() {
431        let class = env.new_string(interfaces[i])?;
432        let face = env
433            .call_static_method(
434                "java/lang/Class",
435                "forName",
436                "(Ljava/lang/String;)Ljava/lang/Class;",
437                &[(&class).into()],
438            )?
439            .l()?;
440        env.set_object_array_element(&faces, i as jsize, &face)?;
441    }
442    let hash_code = env.call_method(&obj, "hashCode", "()I", &[])?.i()?;
443    let res = env.call_static_method(
444        "java/lang/reflect/Proxy",
445        "newProxyInstance",
446        "(Ljava/lang/ClassLoader;[Ljava/lang/Class;Ljava/lang/reflect/InvocationHandler;)Ljava/lang/Object;",
447        &[
448            (&JObject::null()).into(),
449            (&faces).into(),
450            (&obj).into()
451        ]
452    )?
453        .l()?;
454    let res = env.new_global_ref(&res)?;
455    let lock = HOOK_OBJECTS_OTHER.lock();
456    let mut hasher = DefaultHasher::new();
457    res.hash(&mut hasher);
458    lock.borrow_mut().insert(hasher.finish(), hash_code);
459    drop(lock);
460    Ok(res)
461}
462
463//noinspection SpellCheckingInspection
464/// java动态代理绑定rust函数。
465///
466/// # Arguments
467///
468/// * `proxy`: 代理对象。
469/// * `handler`: 一个处理函数。
470///
471/// returns: ()
472///
473/// # 示例
474///
475/// ```
476/// use droid_wrap_utils::{bind_proxy_handler, new_proxy, vm_attach};
477/// let proxy = new_proxy(&["java.lang.Runnable"]).unwrap();
478/// bind_proxy_handler(&proxy, |mut env, method, args| {
479///     let name = env.call_method(&method, "getName", "()Ljava/lang/String;", &[])?.l()?;
480///     let name = env.get_string((&name).into())?;
481///     println!("Method `{}` is called with proxy.", name.to_str()?);
482///     droid_wrap_utils::null_value(env)
483/// });
484/// let mut env = vm_attach().unwrap();
485/// env.call_method(&proxy, "run", "()V", &[]).unwrap();
486/// ```
487pub fn bind_proxy_handler(
488    proxy: &GlobalRef,
489    handler: impl Fn(&mut JNIEnv<'_>, &JObject<'_>, &JObjectArray<'_>) -> Result<GlobalRef>
490    + Send
491    + Sync
492    + 'static,
493) {
494    let hash_code = get_proxy_hash_code(proxy);
495    let lock = match HOOK_OBJECTS.try_lock() {
496        Some(lock) => lock,
497        None => {
498            error!("Can't bind proxy handler.");
499            return;
500        }
501    };
502    lock.borrow_mut().insert(hash_code, Arc::new(handler));
503}
504
505/// 获取java代理对象的哈希值。
506///
507/// # Arguments
508///
509/// * `proxy`: 代理对象。
510///
511/// returns: i32
512///
513/// # 示例
514///
515/// ```
516/// use droid_wrap_utils::{new_proxy, get_proxy_hash_code};
517/// let proxy = new_proxy(&["java.lang.Runnable"]).unwrap();
518/// let hash_code = get_proxy_hash_code(&proxy);
519/// ```
520pub fn get_proxy_hash_code(proxy: &GlobalRef) -> i32 {
521    let mut hasher = DefaultHasher::new();
522    proxy.hash(&mut hasher);
523    let proxy_hash_code = hasher.finish();
524    let lock = HOOK_OBJECTS_OTHER.lock();
525    if let Some(code) = lock.borrow().get(&proxy_hash_code) {
526        return *code;
527    };
528    0
529}
530
531//noinspection SpellCheckingInspection
532/// 删除java动态代理绑定的rust函数。
533///
534/// # Arguments
535///
536/// * `proxy`: Java 代理对象引用。
537///
538/// returns: ()
539///
540/// # 示例
541///
542/// ```
543/// use droid_wrap_utils::{unbind_proxy_handler, new_proxy};
544/// let proxy = new_proxy(&["java.lang.Runnable"]).unwrap();
545/// unbind_proxy_handler(&proxy);
546/// ```
547pub fn unbind_proxy_handler(proxy: &GlobalRef) {
548    let mut hasher = DefaultHasher::new();
549    proxy.hash(&mut hasher);
550    let proxy_hash_code = hasher.finish();
551    let lock = HOOK_OBJECTS_OTHER.lock();
552    if let Some(code) = lock.borrow().get(&proxy_hash_code) {
553        let lock = HOOK_OBJECTS.lock();
554        lock.borrow_mut().remove_entry(code);
555        debug!("Proxy `{}` is dropped.", proxy_hash_code);
556    };
557}
558
559/**
560解析JObject类型。
561*/
562pub trait ParseJObjectType<T: FromStr> {
563    fn parse(&self, env: &mut JNIEnv) -> Result<T>
564    where
565        <T as FromStr>::Err: Debug;
566}
567
568impl<T: FromStr> ParseJObjectType<T> for JObject<'_> {
569    //noinspection SpellCheckingInspection
570    fn parse(&self, env: &mut JNIEnv) -> Result<T>
571    where
572        <T as FromStr>::Err: Debug,
573    {
574        let s = env
575            .call_method(self, "toString", "()Ljava/lang/String;", &[])?
576            .l()?;
577        let s = env.get_string((&s).into())?;
578        let s = s.to_str()?;
579        Ok(s.parse()
580            .map_err(|_| DroidWrapError::FromStr(format!("Invalid value: {}", s)))?)
581    }
582}
583
584//noinspection SpellCheckingInspection
585fn load_rust_call_method_hook_class<'a>() -> Result<&'a GlobalRef> {
586    #[cfg(target_os = "android")]
587    const BYTECODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/classes.dex"));
588    #[cfg(not(target_os = "android"))]
589    const BYTECODE: &[u8] = &[];
590    const LOADER_CLASS: &str = "dalvik/system/InMemoryDexClassLoader";
591    static INSTANCE: OnceLock<Result<GlobalRef>> = OnceLock::new();
592
593    INSTANCE.get_or_init(|| {
594        let mut env = vm_attach()?;
595        let byte_buffer = unsafe { env.new_direct_byte_buffer(BYTECODE.as_ptr() as *mut u8, BYTECODE.len()) }?;
596
597        let dex_class_loader = env
598            .new_object(
599                LOADER_CLASS,
600                "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V",
601                &[
602                    JValueGen::Object(&JObject::from(byte_buffer)),
603                    JValueGen::Object(&JObject::null()),
604                ],
605            )?;
606
607        let class = env.new_string("rust/CallMethodHook")?;
608        let class = env
609            .call_method(
610                &dex_class_loader,
611                "loadClass",
612                "(Ljava/lang/String;)Ljava/lang/Class;",
613                &[(&class).into()],
614            )?
615            .l()?;
616        let m = NativeMethod {
617            name: "invoke".into(),
618            sig: "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;".into(),
619            fn_ptr: rust_callback as *mut _,
620        };
621        env.register_native_methods(Into::<&JClass<'_>>::into(&class), &[m])?;
622
623        Ok(env.new_global_ref(&class)?)
624    }).as_ref().map_err(|e| e.clone())
625}
626
627//noinspection SpellCheckingInspection
628unsafe extern "C" fn rust_callback<'a>(
629    mut env: JNIEnv<'a>,
630    this: JObject<'a>,
631    _: JObject<'a>,
632    method: JObject<'a>,
633    args: JObjectArray<'a>,
634) -> JObject<'a> {
635    fn get_hash_code<'a>(env: &mut JNIEnv<'a>, this: &JObject<'a>) -> Result<i32> {
636        Ok::<_, DroidWrapError>(env.call_method(this, "hashCode", "()I", &[])?.i()?)
637    }
638
639    fn get_name<'a>(env: &mut JNIEnv<'a>, method: &JObject<'a>) -> Result<String> {
640        let name = env
641            .call_method(method, "getName", "()Ljava/lang/String;", &[])?
642            .l()?;
643        Ok::<_, DroidWrapError>(env.get_string((&name).into())?.to_str()?.to_string())
644    }
645
646    let hash_code = get_hash_code(&mut env, &this).unwrap_or_default();
647
648    match get_name(&mut env, &method).unwrap_or_default().as_str() {
649        "toString" => {
650            return match env.new_string(format!("Proxy@{:x}", hash_code).as_str()) {
651                Ok(r) => r.into(),
652                _ => JObject::null(),
653            };
654        }
655        "equals" | "hashCode" => {
656            return match env.call_method(
657                &method,
658                "invoke",
659                "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;",
660                &[(&this).into(), (&args).into()],
661            ) {
662                Ok(r) => match r.l() {
663                    Ok(r) => r,
664                    Err(e) => {
665                        error!("{}", e);
666                        return JObject::null();
667                    }
668                },
669                Err(e) => {
670                    error!("{}", e);
671                    return JObject::null();
672                }
673            };
674        }
675        _ => (),
676    }
677
678    let lock = HOOK_OBJECTS.lock();
679    let func = if let Some(f) = lock.borrow().get(&hash_code) {
680        f.to_owned()
681    } else {
682        warn!(
683            "The method call has reached, but it appears that the proxy object has been dropped."
684        );
685        return JObject::null();
686    };
687    drop(lock);
688
689    match func(&mut env, &method, &args) {
690        Ok(ret) => match env.new_local_ref(ret.as_obj()) {
691            Ok(r) => return r,
692            Err(e) => {
693                error!("{}", e);
694                JObject::null()
695            }
696        },
697        Err(e) => {
698            error!("{}", e);
699            JObject::null()
700        }
701    }
702}
703
704/// 把java对象数组转换成Vec
705///
706/// # 参数
707///
708/// * `env`: java环境
709/// * `arr`: java数组
710///
711/// # 返回值
712///
713/// 返回: Result<Vec<JObject, Global>>
714///
715/// # 示例
716///
717/// ```
718/// use jni::objects::JObjectArray;
719/// use droid_wrap_utils::{to_vec, vm_attach};
720/// let mut env = vm_attach().unwrap();
721/// unsafe {
722///     let arr=JObjectArray::from_raw(0 as _);
723///     to_vec(&mut env, &arr).unwrap();
724/// }
725/// ```
726pub fn to_vec<'a>(env: &mut JNIEnv<'a>, arr: &JObjectArray) -> Result<Vec<JObject<'a>>> {
727    let size = env.get_array_length(arr)?;
728    let mut arr2 = Vec::with_capacity(size as usize);
729    for i in 0..size {
730        arr2.push(env.get_object_array_element(arr, i)?);
731    }
732
733    Ok(arr2)
734}
735
736/// 将Rust数组转换为Java对象数组
737///
738/// 将一个Rust数组转换为Java数组,其中每个元素都是JObject类型。
739///
740/// # 参数
741///
742/// * `env` - 一个`JNIEnv`类型的引用,用于操作Java虚拟机。
743/// * `arr` - 一个Rust数组,其中每个元素都是实现了`AsRef<JObject<'a>>` trait的类型。
744/// * `element_class` - Java数组元素的类名。
745///
746/// # 返回值
747///
748/// 返回: `Result<JObjectArray>`
749///
750/// # 示例
751///
752/// ```rust
753/// use droid_wrap_utils::{ JNIEnv, JObject, JObjectArray, jint, to_java_object_array, vm_attach };
754///
755/// let mut env = vm_attach().unwrap();
756/// // 假设我们有一个Rust数组
757/// let rust_array = vec![env.new_string("hello").unwrap(), env.new_string("world").unwrap()];
758///
759/// // 将Rust数组转换为Java数组
760/// let java_array = to_java_object_array(&mut env, &rust_array, "java/lang/String").unwrap();
761/// ```
762///
763pub fn to_java_object_array<'a, O: AsRef<JObject<'a>>>(
764    // env:JNIEnv<'a>类型,用于操作Java虚拟机
765    env: &mut JNIEnv<'a>,
766    // arr:Rust数组,类型为O,O需要实现AsRef<JObject<'a>> trait
767    arr: &[O],
768    // element_class:Java数组元素的类名
769    element_class: &str,
770) -> Result<JObjectArray<'a>> {
771    // 创建一个新的Java数组,长度为arr.len(),元素类型为element_class,初始值为JObject::null()
772    let arr2 = env.new_object_array(arr.len() as _, element_class, JObject::null())?;
773    // 遍历Rust数组,将每个元素设置为Java数组的对应位置
774    for (i, j) in arr.iter().enumerate() {
775        env.set_object_array_element(&arr2, i as _, j)?;
776    }
777
778    // 返回Java数组
779    Ok(arr2)
780}
781
782//noinspection SpellCheckingInspection
783/// 将Rust数组转换为Java byte数组
784///
785/// 将一个Rust数组转换为Java数组,其中每个元素都是jbyte类型。
786///
787/// # 参数
788///
789/// * `env` - 一个`JNIEnv`类型的引用,用于操作Java虚拟机。
790/// * `arr` - 一个Rust数组。
791///
792/// # 返回值
793///
794/// 返回一个`JBooleanArray`类型的Java数组。
795///
796/// # 示例
797///
798/// ```rust
799/// use droid_wrap_utils::{ JNIEnv, JBooleanArray, jint, to_java_byte_array, vm_attach };
800///
801/// let mut env = vm_attach().unwrap();
802/// // 假设我们有一个Rust数组
803/// let rust_array = vec![65i8,66,67];
804///
805/// // 将Rust数组转换为Java数组
806/// let java_array = to_java_byte_array(&mut env, &rust_array).unwrap();
807/// ```
808///
809pub fn to_java_byte_array<'a>(
810    // env:JNIEnv<'a>类型,用于操作Java虚拟机
811    env: &mut JNIEnv<'a>,
812    // arr:Rust[u8]数组
813    arr: &[jbyte],
814) -> Result<JByteArray<'a>> {
815    // 创建一个新的Java数组,长度为arr.len(),元素类型为element_class,初始值为JObject::null()
816    let arr2 = env.new_byte_array(arr.len() as _)?;
817    // 遍历Rust数组,将每个元素设置为Java数组的对应位置
818    env.set_byte_array_region(&arr2, 0, arr)?;
819    // 返回Java数组
820    Ok(arr2)
821}
822
823/// 获取null的全局引用值。
824///
825/// # 参数
826///
827/// * `env`: jni环境。
828///
829/// # 返回值
830///
831/// 返回: `Result<GlobalRef>`
832///
833/// # 示例
834///
835/// ```
836/// use droid_wrap_utils::{null_value, vm_attach};
837/// let mut env = vm_attach().unwrap();
838/// let null_value = null_value(&mut env);
839/// ```
840pub fn null_value(env: &mut JNIEnv) -> Result<GlobalRef> {
841    let obj = JObject::null();
842    Ok(env.new_global_ref(&obj)?)
843}
844
845/// 获取boolean的包装对象的全局引用值。
846///
847/// # 参数
848///
849/// * `value`: 数据。
850/// * `env`: jni环境。
851///
852/// # 返回值
853///
854/// 返回: `Result<GlobalRef>`
855///
856/// # 示例
857///
858/// ```
859/// use droid_wrap_utils::{vm_attach, wrapper_bool_value};
860/// let mut env = vm_attach().unwrap();
861/// let true_value = wrapper_bool_value(true, &mut env).unwrap();
862/// ```
863pub fn wrapper_bool_value(value: bool, env: &mut JNIEnv) -> Result<GlobalRef> {
864    let obj = env.new_object("java/lang/Boolean", "(Z)V", &[(value as jboolean).into()])?;
865    Ok(env.new_global_ref(&obj)?)
866}
867
868/// 获取int的包装对象的全局引用值。
869///
870/// # 参数
871///
872/// * `value`: 数据。
873/// * `env`: jni环境。
874///
875/// # 返回值
876///
877/// 返回: `Result<GlobalRef>`
878///
879/// # 示例
880///
881/// ```
882/// use droid_wrap_utils::{vm_attach, wrapper_integer_value};
883/// let mut env = vm_attach().unwrap();
884/// let zero_value = wrapper_integer_value(0, &mut env).unwrap();
885/// ```
886pub fn wrapper_integer_value(value: i32, env: &mut JNIEnv) -> Result<GlobalRef> {
887    let obj = env.new_object("java/lang/Integer", "(I)V", &[value.into()])?;
888    Ok(env.new_global_ref(&obj)?)
889}
890
891/// 获取long的包装对象的全局引用值。
892///
893/// # 参数
894///
895/// * `value`: 数据。
896/// * `env`: jni环境。
897///
898/// # 返回值
899///
900/// 返回: `Result<GlobalRef>`
901///
902/// # 示例
903///
904/// ```
905/// use droid_wrap_utils::{vm_attach, wrapper_long_value};
906/// let mut env = vm_attach().unwrap();
907/// let zero_value = wrapper_long_value(0, &mut env).unwrap();
908/// ```
909pub fn wrapper_long_value(value: i64, env: &mut JNIEnv) -> Result<GlobalRef> {
910    let obj = env.new_object("java/lang/Long", "(J)V", &[value.into()])?;
911    Ok(env.new_global_ref(&obj)?)
912}
913
914//noinspection SpellCheckingInspection
915/// 比较两个Java对象是否相等。
916///
917/// # 参数
918///
919/// * `a`: 第一个对象。
920/// * `b`: 第二个对象。
921///
922/// # 返回值
923///
924/// 返回: `Result<bool>`
925///
926/// # 示例
927///
928/// ```
929/// use droid_wrap_utils::{vm_attach, java_object_equals};
930/// let mut env = vm_attach().unwrap();
931/// let obj1 = env.new_object("java/lang/Object", "()V", &[]).unwrap();
932/// let obj2 = env.new_object("java/lang/Object", "()V", &[]).unwrap();
933/// let equal = java_object_equals(obj1, obj2).unwrap();
934/// ```
935pub fn java_object_equals<'a, O: AsRef<JObject<'a>>>(a: O, b: O) -> Result<bool> {
936    let a = a.as_ref();
937    let b = b.as_ref();
938    if a.is_null() && a.is_null() {
939        return Ok(true);
940    }
941    if a.is_null() {
942        return Ok(false);
943    }
944    let mut env = vm_attach()?;
945    let res = env
946        .call_method(a, "equals", "(Ljava/lang/Object;)Z", &[b.into()])?
947        .z()?;
948
949    Ok(res)
950}
951
952//noinspection SpellCheckingInspection
953/// 将Java对象转换为字符串。
954///
955/// # 参数
956///
957/// * `obj`: Java对象。
958///
959/// # 返回值
960///
961/// 返回: `Result<String>`
962///
963/// # 示例
964///
965/// ```
966/// use droid_wrap_utils::{vm_attach, java_object_to_string};
967/// let mut env = vm_attach().unwrap();
968/// let obj = env.new_object("java/lang/Object", "()V", &[]).unwrap();
969/// let s = java_object_to_string(obj).unwrap();
970/// ```
971pub fn java_object_to_string<'a, O: AsRef<JObject<'a>>>(obj: O) -> Result<String> {
972    let obj = obj.as_ref();
973    if obj.is_null() {
974        return Err(DroidWrapError::Jni(JniError::NullPtr("to_string")));
975    }
976    let mut env = vm_attach()?;
977    let s = env
978        .call_method(obj, "toString", "()Ljava/lang/String;", &[])?
979        .l()?;
980    let s = env.get_string((&s).into())?;
981
982    Ok(s.to_str()?.to_string())
983}