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