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
289    (u8, $dim:expr) => {
290        impl JObjNew for &[u8] {
291            type Fields = ();
292
293            fn _new(this: &GlobalRef, fields: Self::Fields) -> Result<Self> {
294                Ok(&[])
295            }
296        }
297
298        impl JObjRef for &[u8] {
299            fn java_ref(&self) -> Result<GlobalRef> {
300                let mut env = vm_attach()?;
301                let arr = self.iter().map(|i| *i as _).collect::<Vec<_>>();
302                let arr = to_java_byte_array(&mut env, &arr)?;
303                Ok(env.new_global_ref(&arr)?)
304            }
305        }
306
307        impl JType for &[u8] {
308            const CLASS: &'static str = "B";
309            const OBJECT_SIG: &'static str = "B";
310            const DIM: u8 = $dim;
311        }
312    };
313}
314
315/**
316获取android系统的java虚拟机。
317*/
318pub fn android_vm<'a>() -> Result<&'static JavaVM> {
319    static JAVA_VM: LazyLock<Result<JavaVM>> = LazyLock::new(|| {
320        let ctx = ndk_context::android_context();
321        let vm = unsafe { JavaVM::from_raw(ctx.vm().cast()) }?;
322        Ok(vm)
323    });
324    JAVA_VM.as_ref().map_err(|e| e.to_owned())
325}
326
327/// 获取vm,将vm附加到当前线程,随后操作java虚拟机。
328///
329/// # 示例
330///
331/// ```
332/// use droid_wrap_utils::{vm_attach, Result};
333/// fn main() -> Result<()> {
334/// let mut env = vm_attach()?;
335/// let class = env.find_class("java/lang/String");
336/// dbg!(class)
337/// }
338/// ```
339#[inline(always)]
340pub fn vm_attach<'a>() -> Result<AttachGuard<'a>> {
341    let vm = android_vm()?;
342    vm.attach_current_thread().map_err(|e| e.into())
343}
344
345/**
346获取安卓的Context对象,这通常是NativeActivity对象的引用。
347*/
348pub fn android_context<'a>() -> JObject<'a> {
349    let ctx = ndk_context::android_context();
350    unsafe { JObject::from_raw(ctx.context().cast()) }
351}
352
353/// 创建一个java动态代理,用于在rust层实现java接口的方法。
354///
355/// # Arguments
356///
357/// * `interfaces`: 要实现的java接口。
358/// * `handler`: 代理的处理函数。
359///
360/// 返回: `Result<GlobalRef>` 代理对象
361///
362/// # 示例
363///
364/// ```
365/// use droid_wrap_utils::new_proxy;
366/// let proxy = new_proxy(&["java.lang.Runnable"]);
367/// ```
368//noinspection SpellCheckingInspection
369pub fn new_proxy(interfaces: &[&str]) -> Result<GlobalRef> {
370    let class = load_rust_call_method_hook_class()?;
371    let mut env = vm_attach()?;
372    let obj = env.new_object(class, "()V", &[])?;
373    let faces = env.new_object_array(
374        interfaces.len() as jsize,
375        "java/lang/Class",
376        &JObject::null(),
377    )?;
378    for i in 0..interfaces.len() {
379        let class = env.new_string(interfaces[i])?;
380        let face = env
381            .call_static_method(
382                "java/lang/Class",
383                "forName",
384                "(Ljava/lang/String;)Ljava/lang/Class;",
385                &[(&class).into()],
386            )?
387            .l()?;
388        env.set_object_array_element(&faces, i as jsize, &face)?;
389    }
390    let hash_code = env.call_method(&obj, "hashCode", "()I", &[])?.i()?;
391    let res = env.call_static_method(
392        "java/lang/reflect/Proxy",
393        "newProxyInstance",
394        "(Ljava/lang/ClassLoader;[Ljava/lang/Class;Ljava/lang/reflect/InvocationHandler;)Ljava/lang/Object;",
395        &[
396            (&JObject::null()).into(),
397            (&faces).into(),
398            (&obj).into()
399        ]
400    )?
401        .l()?;
402    let res = env.new_global_ref(&res)?;
403    let lock = HOOK_OBJECTS_OTHER.lock();
404    let mut hasher = DefaultHasher::new();
405    res.hash(&mut hasher);
406    lock.borrow_mut().insert(hasher.finish(), hash_code);
407    drop(lock);
408    Ok(res)
409}
410
411//noinspection SpellCheckingInspection
412/// java动态代理绑定rust函数。
413///
414/// # Arguments
415///
416/// * `proxy`: 代理对象。
417/// * `handler`: 一个处理函数。
418///
419/// returns: ()
420///
421/// # 示例
422///
423/// ```
424/// use droid_wrap_utils::{bind_proxy_handler, new_proxy, vm_attach};
425/// let proxy = new_proxy(&["java.lang.Runnable"]).unwrap();
426/// bind_proxy_handler(&proxy, |mut env, method, args| {
427///     let name = env.call_method(&method, "getName", "()Ljava/lang/String;", &[])?.l()?;
428///     let name = env.get_string((&name).into())?;
429///     println!("Method `{}` is called with proxy.", name.to_str()?);
430///     droid_wrap_utils::null_value(env)
431/// });
432/// let mut env = vm_attach().unwrap();
433/// env.call_method(&proxy, "run", "()V", &[]).unwrap();
434/// ```
435pub fn bind_proxy_handler(
436    proxy: &GlobalRef,
437    handler: impl Fn(&mut JNIEnv<'_>, &JObject<'_>, &JObjectArray<'_>) -> Result<GlobalRef>
438    + Send
439    + Sync
440    + 'static,
441) {
442    let hash_code = get_proxy_hash_code(proxy);
443    let lock = match HOOK_OBJECTS.try_lock() {
444        Some(lock) => lock,
445        None => {
446            error!("Can't bind proxy handler.");
447            return;
448        }
449    };
450    lock.borrow_mut().insert(hash_code, Arc::new(handler));
451}
452
453/// 获取java代理对象的哈希值。
454///
455/// # Arguments
456///
457/// * `proxy`: 代理对象。
458///
459/// returns: i32
460///
461/// # 示例
462///
463/// ```
464/// use droid_wrap_utils::{new_proxy, get_proxy_hash_code};
465/// let proxy = new_proxy(&["java.lang.Runnable"]).unwrap();
466/// let hash_code = get_proxy_hash_code(&proxy);
467/// ```
468pub fn get_proxy_hash_code(proxy: &GlobalRef) -> i32 {
469    let mut hasher = DefaultHasher::new();
470    proxy.hash(&mut hasher);
471    let proxy_hash_code = hasher.finish();
472    let lock = HOOK_OBJECTS_OTHER.lock();
473    if let Some(code) = lock.borrow().get(&proxy_hash_code) {
474        return *code;
475    };
476    0
477}
478
479//noinspection SpellCheckingInspection
480/// 删除java动态代理绑定的rust函数。
481///
482/// # Arguments
483///
484/// * `proxy`: Java 代理对象引用。
485///
486/// returns: ()
487///
488/// # 示例
489///
490/// ```
491/// use droid_wrap_utils::{unbind_proxy_handler, new_proxy};
492/// let proxy = new_proxy(&["java.lang.Runnable"]).unwrap();
493/// unbind_proxy_handler(&proxy);
494/// ```
495pub fn unbind_proxy_handler(proxy: &GlobalRef) {
496    let mut hasher = DefaultHasher::new();
497    proxy.hash(&mut hasher);
498    let proxy_hash_code = hasher.finish();
499    let lock = HOOK_OBJECTS_OTHER.lock();
500    if let Some(code) = lock.borrow().get(&proxy_hash_code) {
501        let lock = HOOK_OBJECTS.lock();
502        lock.borrow_mut().remove_entry(code);
503        debug!("Proxy `{}` is dropped.", proxy_hash_code);
504    };
505}
506
507/**
508解析JObject类型。
509*/
510pub trait ParseJObjectType<T: FromStr> {
511    fn parse(&self, env: &mut JNIEnv) -> Result<T>
512    where
513        <T as FromStr>::Err: Debug;
514}
515
516impl<T: FromStr> ParseJObjectType<T> for JObject<'_> {
517    //noinspection SpellCheckingInspection
518    fn parse(&self, env: &mut JNIEnv) -> Result<T>
519    where
520        <T as FromStr>::Err: Debug,
521    {
522        let s = env
523            .call_method(self, "toString", "()Ljava/lang/String;", &[])?
524            .l()?;
525        let s = env.get_string((&s).into())?;
526        let s = s.to_str()?;
527        Ok(s.parse()
528            .map_err(|_| DroidWrapError::FromStr(format!("Invalid value: {}", s)))?)
529    }
530}
531
532//noinspection SpellCheckingInspection
533fn load_rust_call_method_hook_class<'a>() -> Result<&'a GlobalRef> {
534    #[cfg(target_os = "android")]
535    const BYTECODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/classes.dex"));
536    #[cfg(not(target_os = "android"))]
537    const BYTECODE: &[u8] = &[];
538    const LOADER_CLASS: &str = "dalvik/system/InMemoryDexClassLoader";
539    static INSTANCE: OnceLock<Result<GlobalRef>> = OnceLock::new();
540
541    INSTANCE.get_or_init(|| {
542        let mut env = vm_attach()?;
543        let byte_buffer = unsafe { env.new_direct_byte_buffer(BYTECODE.as_ptr() as *mut u8, BYTECODE.len()) }?;
544
545        let dex_class_loader = env
546            .new_object(
547                LOADER_CLASS,
548                "(Ljava/nio/ByteBuffer;Ljava/lang/ClassLoader;)V",
549                &[
550                    JValueGen::Object(&JObject::from(byte_buffer)),
551                    JValueGen::Object(&JObject::null()),
552                ],
553            )?;
554
555        let class = env.new_string("rust/CallMethodHook")?;
556        let class = env
557            .call_method(
558                &dex_class_loader,
559                "loadClass",
560                "(Ljava/lang/String;)Ljava/lang/Class;",
561                &[(&class).into()],
562            )?
563            .l()?;
564        let m = NativeMethod {
565            name: "invoke".into(),
566            sig: "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;".into(),
567            fn_ptr: rust_callback as *mut _,
568        };
569        env.register_native_methods(Into::<&JClass<'_>>::into(&class), &[m])?;
570
571        Ok(env.new_global_ref(&class)?)
572    }).as_ref().map_err(|e| e.clone())
573}
574
575//noinspection SpellCheckingInspection
576unsafe extern "C" fn rust_callback<'a>(
577    mut env: JNIEnv<'a>,
578    this: JObject<'a>,
579    _: JObject<'a>,
580    method: JObject<'a>,
581    args: JObjectArray<'a>,
582) -> JObject<'a> {
583    fn get_hash_code<'a>(env: &mut JNIEnv<'a>, this: &JObject<'a>) -> Result<i32> {
584        Ok::<_, DroidWrapError>(env.call_method(this, "hashCode", "()I", &[])?.i()?)
585    }
586
587    fn get_name<'a>(env: &mut JNIEnv<'a>, method: &JObject<'a>) -> Result<String> {
588        let name = env
589            .call_method(method, "getName", "()Ljava/lang/String;", &[])?
590            .l()?;
591        Ok::<_, DroidWrapError>(env.get_string((&name).into())?.to_str()?.to_string())
592    }
593
594    let hash_code = get_hash_code(&mut env, &this).unwrap_or_default();
595
596    match get_name(&mut env, &method).unwrap_or_default().as_str() {
597        "toString" => {
598            return match env.new_string(format!("Proxy@{:x}", hash_code).as_str()) {
599                Ok(r) => r.into(),
600                _ => JObject::null(),
601            };
602        }
603        "equals" | "hashCode" => {
604            return match env.call_method(
605                &method,
606                "invoke",
607                "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;",
608                &[(&this).into(), (&args).into()],
609            ) {
610                Ok(r) => match r.l() {
611                    Ok(r) => r,
612                    Err(e) => {
613                        error!("{}", e);
614                        return JObject::null();
615                    }
616                },
617                Err(e) => {
618                    error!("{}", e);
619                    return JObject::null();
620                }
621            };
622        }
623        _ => (),
624    }
625
626    let lock = HOOK_OBJECTS.lock();
627    let func = if let Some(f) = lock.borrow().get(&hash_code) {
628        f.to_owned()
629    } else {
630        warn!(
631            "The method call has reached, but it appears that the proxy object has been dropped."
632        );
633        return JObject::null();
634    };
635    drop(lock);
636
637    match func(&mut env, &method, &args) {
638        Ok(ret) => match env.new_local_ref(ret.as_obj()) {
639            Ok(r) => return r,
640            Err(e) => {
641                error!("{}", e);
642                JObject::null()
643            }
644        },
645        Err(e) => {
646            error!("{}", e);
647            JObject::null()
648        }
649    }
650}
651
652/// 把java对象数组转换成Vec
653///
654/// # 参数
655///
656/// * `env`: java环境
657/// * `arr`: java数组
658///
659/// # 返回值
660///
661/// 返回: Result<Vec<JObject, Global>>
662///
663/// # 示例
664///
665/// ```
666/// use jni::objects::JObjectArray;
667/// use droid_wrap_utils::{to_vec, vm_attach};
668/// let mut env = vm_attach().unwrap();
669/// unsafe {
670///     let arr=JObjectArray::from_raw(0 as _);
671///     to_vec(&mut env, &arr).unwrap();
672/// }
673/// ```
674pub fn to_vec<'a>(env: &mut JNIEnv<'a>, arr: &JObjectArray) -> Result<Vec<JObject<'a>>> {
675    let size = env.get_array_length(arr)?;
676    let mut arr2 = Vec::with_capacity(size as usize);
677    for i in 0..size {
678        arr2.push(env.get_object_array_element(arr, i)?);
679    }
680
681    Ok(arr2)
682}
683
684/// 将Rust数组转换为Java对象数组
685///
686/// 将一个Rust数组转换为Java数组,其中每个元素都是JObject类型。
687///
688/// # 参数
689///
690/// * `env` - 一个`JNIEnv`类型的引用,用于操作Java虚拟机。
691/// * `arr` - 一个Rust数组,其中每个元素都是实现了`AsRef<JObject<'a>>` trait的类型。
692/// * `element_class` - Java数组元素的类名。
693///
694/// # 返回值
695///
696/// 返回: `Result<JObjectArray>`
697///
698/// # 示例
699///
700/// ```rust
701/// use droid_wrap_utils::{ JNIEnv, JObject, JObjectArray, jint, to_java_object_array, vm_attach };
702///
703/// let mut env = vm_attach().unwrap();
704/// // 假设我们有一个Rust数组
705/// let rust_array = vec![env.new_string("hello").unwrap(), env.new_string("world").unwrap()];
706///
707/// // 将Rust数组转换为Java数组
708/// let java_array = to_java_object_array(&mut env, &rust_array, "java/lang/String").unwrap();
709/// ```
710///
711pub fn to_java_object_array<'a, O: AsRef<JObject<'a>>>(
712    // env:JNIEnv<'a>类型,用于操作Java虚拟机
713    env: &mut JNIEnv<'a>,
714    // arr:Rust数组,类型为O,O需要实现AsRef<JObject<'a>> trait
715    arr: &[O],
716    // element_class:Java数组元素的类名
717    element_class: &str,
718) -> Result<JObjectArray<'a>> {
719    // 创建一个新的Java数组,长度为arr.len(),元素类型为element_class,初始值为JObject::null()
720    let arr2 = env.new_object_array(arr.len() as _, element_class, JObject::null())?;
721    // 遍历Rust数组,将每个元素设置为Java数组的对应位置
722    for (i, j) in arr.iter().enumerate() {
723        env.set_object_array_element(&arr2, i as _, j)?;
724    }
725
726    // 返回Java数组
727    Ok(arr2)
728}
729
730//noinspection SpellCheckingInspection
731/// 将Rust数组转换为Java byte数组
732///
733/// 将一个Rust数组转换为Java数组,其中每个元素都是jbyte类型。
734///
735/// # 参数
736///
737/// * `env` - 一个`JNIEnv`类型的引用,用于操作Java虚拟机。
738/// * `arr` - 一个Rust数组。
739///
740/// # 返回值
741///
742/// 返回一个`JBooleanArray`类型的Java数组。
743///
744/// # 示例
745///
746/// ```rust
747/// use droid_wrap_utils::{ JNIEnv, JBooleanArray, jint, to_java_byte_array, vm_attach };
748///
749/// let mut env = vm_attach().unwrap();
750/// // 假设我们有一个Rust数组
751/// let rust_array = vec![65i8,66,67];
752///
753/// // 将Rust数组转换为Java数组
754/// let java_array = to_java_byte_array(&mut env, &rust_array).unwrap();
755/// ```
756///
757pub fn to_java_byte_array<'a>(
758    // env:JNIEnv<'a>类型,用于操作Java虚拟机
759    env: &mut JNIEnv<'a>,
760    // arr:Rust[u8]数组
761    arr: &[jbyte],
762) -> Result<JByteArray<'a>> {
763    // 创建一个新的Java数组,长度为arr.len(),元素类型为element_class,初始值为JObject::null()
764    let arr2 = env.new_byte_array(arr.len() as _)?;
765    // 遍历Rust数组,将每个元素设置为Java数组的对应位置
766    env.set_byte_array_region(&arr2, 0, arr)?;
767    // 返回Java数组
768    Ok(arr2)
769}
770
771/// 获取null的全局引用值。
772///
773/// # 参数
774///
775/// * `env`: jni环境。
776///
777/// # 返回值
778///
779/// 返回: `Result<GlobalRef>`
780///
781/// # 示例
782///
783/// ```
784/// use droid_wrap_utils::{null_value, vm_attach};
785/// let mut env = vm_attach().unwrap();
786/// let null_value = null_value(&mut env);
787/// ```
788pub fn null_value(env: &mut JNIEnv) -> Result<GlobalRef> {
789    let obj = JObject::null();
790    Ok(env.new_global_ref(&obj)?)
791}
792
793/// 获取boolean的包装对象的全局引用值。
794///
795/// # 参数
796///
797/// * `value`: 数据。
798/// * `env`: jni环境。
799///
800/// # 返回值
801///
802/// 返回: `Result<GlobalRef>`
803///
804/// # 示例
805///
806/// ```
807/// use droid_wrap_utils::{vm_attach, wrapper_bool_value};
808/// let mut env = vm_attach().unwrap();
809/// let true_value = wrapper_bool_value(true, &mut env).unwrap();
810/// ```
811pub fn wrapper_bool_value(value: bool, env: &mut JNIEnv) -> Result<GlobalRef> {
812    let obj = env.new_object("java/lang/Boolean", "(Z)V", &[(value as jboolean).into()])?;
813    Ok(env.new_global_ref(&obj)?)
814}
815
816/// 获取int的包装对象的全局引用值。
817///
818/// # 参数
819///
820/// * `value`: 数据。
821/// * `env`: jni环境。
822///
823/// # 返回值
824///
825/// 返回: `Result<GlobalRef>`
826///
827/// # 示例
828///
829/// ```
830/// use droid_wrap_utils::{vm_attach, wrapper_integer_value};
831/// let mut env = vm_attach().unwrap();
832/// let zero_value = wrapper_integer_value(0, &mut env).unwrap();
833/// ```
834pub fn wrapper_integer_value(value: i32, env: &mut JNIEnv) -> Result<GlobalRef> {
835    let obj = env.new_object("java/lang/Integer", "(I)V", &[value.into()])?;
836    Ok(env.new_global_ref(&obj)?)
837}
838
839/// 获取long的包装对象的全局引用值。
840///
841/// # 参数
842///
843/// * `value`: 数据。
844/// * `env`: jni环境。
845///
846/// # 返回值
847///
848/// 返回: `Result<GlobalRef>`
849///
850/// # 示例
851///
852/// ```
853/// use droid_wrap_utils::{vm_attach, wrapper_long_value};
854/// let mut env = vm_attach().unwrap();
855/// let zero_value = wrapper_long_value(0, &mut env).unwrap();
856/// ```
857pub fn wrapper_long_value(value: i64, env: &mut JNIEnv) -> Result<GlobalRef> {
858    let obj = env.new_object("java/lang/Long", "(J)V", &[value.into()])?;
859    Ok(env.new_global_ref(&obj)?)
860}
861
862//noinspection SpellCheckingInspection
863/// 比较两个Java对象是否相等。
864///
865/// # 参数
866///
867/// * `a`: 第一个对象。
868/// * `b`: 第二个对象。
869///
870/// # 返回值
871///
872/// 返回: `Result<bool>`
873///
874/// # 示例
875///
876/// ```
877/// use droid_wrap_utils::{vm_attach, java_object_equals};
878/// let mut env = vm_attach().unwrap();
879/// let obj1 = env.new_object("java/lang/Object", "()V", &[]).unwrap();
880/// let obj2 = env.new_object("java/lang/Object", "()V", &[]).unwrap();
881/// let equal = java_object_equals(obj1, obj2).unwrap();
882/// ```
883pub fn java_object_equals<'a, O: AsRef<JObject<'a>>>(a: O, b: O) -> Result<bool> {
884    let a = a.as_ref();
885    let b = b.as_ref();
886    if a.is_null() && a.is_null() {
887        return Ok(true);
888    }
889    if a.is_null() {
890        return Ok(false);
891    }
892    let mut env = vm_attach()?;
893    let res = env
894        .call_method(a, "equals", "(Ljava/lang/Object;)Z", &[b.into()])?
895        .z()?;
896
897    Ok(res)
898}
899
900//noinspection SpellCheckingInspection
901/// 将Java对象转换为字符串。
902///
903/// # 参数
904///
905/// * `obj`: Java对象。
906///
907/// # 返回值
908///
909/// 返回: `Result<String>`
910///
911/// # 示例
912///
913/// ```
914/// use droid_wrap_utils::{vm_attach, java_object_to_string};
915/// let mut env = vm_attach().unwrap();
916/// let obj = env.new_object("java/lang/Object", "()V", &[]).unwrap();
917/// let s = java_object_to_string(obj).unwrap();
918/// ```
919pub fn java_object_to_string<'a, O: AsRef<JObject<'a>>>(obj: O) -> Result<String> {
920    let obj = obj.as_ref();
921    if obj.is_null() {
922        return Err(DroidWrapError::Jni(JniError::NullPtr("to_string")));
923    }
924    let mut env = vm_attach()?;
925    let s = env
926        .call_method(obj, "toString", "()Ljava/lang/String;", &[])?
927        .l()?;
928    let s = env.get_string((&s).into())?;
929
930    Ok(s.to_str()?.to_string())
931}