jni_helpers.rs 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use crate::Runtime;
  5. use jni::{
  6. errors::Error as JniError,
  7. objects::{JObject, JValueOwned},
  8. JNIEnv,
  9. };
  10. use serde_json::Value as JsonValue;
  11. use tauri_runtime::RuntimeHandle;
  12. fn json_to_java<'a, R: Runtime>(
  13. env: &mut JNIEnv<'a>,
  14. activity: &JObject<'_>,
  15. runtime_handle: &R::Handle,
  16. json: &JsonValue,
  17. ) -> Result<(&'static str, JValueOwned<'a>), JniError> {
  18. let (class, v) = match json {
  19. JsonValue::Null => ("Ljava/lang/Object;", JObject::null().into()),
  20. JsonValue::Bool(val) => ("Z", (*val).into()),
  21. JsonValue::Number(val) => {
  22. if let Some(v) = val.as_i64() {
  23. ("J", v.into())
  24. } else if let Some(v) = val.as_f64() {
  25. ("D", v.into())
  26. } else {
  27. ("Ljava/lang/Object;", JObject::null().into())
  28. }
  29. }
  30. JsonValue::String(val) => (
  31. "Ljava/lang/Object;",
  32. JObject::from(env.new_string(val)?).into(),
  33. ),
  34. JsonValue::Array(val) => {
  35. let js_array_class = runtime_handle.find_class(env, activity, "app/tauri/plugin/JSArray")?;
  36. let data = env.new_object(js_array_class, "()V", &[])?;
  37. for v in val {
  38. let (signature, val) = json_to_java::<R>(env, activity, runtime_handle, v)?;
  39. env.call_method(
  40. &data,
  41. "put",
  42. format!("({signature})Lorg/json/JSONArray;"),
  43. &[val.borrow()],
  44. )?;
  45. }
  46. ("Ljava/lang/Object;", data.into())
  47. }
  48. JsonValue::Object(val) => {
  49. let data = {
  50. let js_object_class =
  51. runtime_handle.find_class(env, activity, "app/tauri/plugin/JSObject")?;
  52. env.new_object(js_object_class, "()V", &[])?
  53. };
  54. for (key, value) in val {
  55. let (signature, val) = json_to_java::<R>(env, activity, runtime_handle, value)?;
  56. let key = env.new_string(key)?;
  57. env.call_method(
  58. &data,
  59. "put",
  60. format!("(Ljava/lang/String;{signature})Lapp/tauri/plugin/JSObject;"),
  61. &[(&key).into(), val.borrow()],
  62. )?;
  63. }
  64. ("Ljava/lang/Object;", data.into())
  65. }
  66. };
  67. Ok((class, v))
  68. }
  69. pub fn to_jsobject<'a, R: Runtime>(
  70. env: &mut JNIEnv<'a>,
  71. activity: &JObject<'_>,
  72. runtime_handle: &R::Handle,
  73. json: &JsonValue,
  74. ) -> Result<JValueOwned<'a>, JniError> {
  75. if let JsonValue::Object(_) = json {
  76. json_to_java::<R>(env, activity, runtime_handle, json).map(|(_class, data)| data)
  77. } else {
  78. Ok(empty_object::<R>(env, activity, runtime_handle)?.into())
  79. }
  80. }
  81. fn empty_object<'a, R: Runtime>(
  82. env: &mut JNIEnv<'a>,
  83. activity: &JObject<'_>,
  84. runtime_handle: &R::Handle,
  85. ) -> Result<JObject<'a>, JniError> {
  86. // currently the Kotlin lib cannot handle nulls or raw values, it must be an object
  87. let js_object_class = runtime_handle.find_class(env, activity, "app/tauri/plugin/JSObject")?;
  88. let data = env.new_object(js_object_class, "()V", &[])?;
  89. Ok(data)
  90. }