android_native_keyring_store/
shared_preferences.rs1use crate::methods::{ClassDecl, FromValue, JResult, Method, NoParam, SignatureComp};
2use base64::{Engine, prelude::BASE64_STANDARD};
3use jni::{
4 JNIEnv,
5 objects::{GlobalRef, JObject},
6};
7use std::marker::PhantomData;
8
9#[derive(Clone)]
10pub struct Context {
11 self_: GlobalRef,
12}
13impl Context {
14 pub fn new(env: &JNIEnv, obj: JObject) -> JResult<Self> {
15 Ok(Self {
16 self_: env.new_global_ref(obj)?,
17 })
18 }
19
20 pub fn get_shared_preferences(
21 &self,
22 env: &mut JNIEnv,
23 name: &str,
24 mode: i32,
25 ) -> JResult<SharedPreferences> {
26 struct ThisMethod<'a>(PhantomData<&'a ()>);
27 impl<'a> Method for ThisMethod<'a> {
28 type Param = (&'a str, i32);
29 type Return = SharedPreferences;
30
31 const NAME: &'static str = "getSharedPreferences";
32 }
33
34 ThisMethod::call(&self.self_, env, (name, mode))
35 }
36
37 pub fn id(&self) -> usize {
38 self.self_.as_raw() as usize
39 }
40}
41
42pub struct SharedPreferences {
43 self_: GlobalRef,
44}
45impl FromValue for SharedPreferences {
46 fn signature() -> SignatureComp {
47 Self::class().into()
48 }
49
50 fn from_object(self_: GlobalRef, _env: &mut JNIEnv) -> JResult<Self> {
51 Ok(Self { self_ })
52 }
53}
54impl SharedPreferences {
55 fn class() -> ClassDecl {
56 ClassDecl("Landroid/content/SharedPreferences;")
57 }
58
59 pub fn get_string(&self, env: &mut JNIEnv, key: &str) -> JResult<Option<String>> {
60 struct ThisMethod<'a>(PhantomData<&'a ()>);
61 impl<'a> Method for ThisMethod<'a> {
62 type Param = (&'a str, Option<&'a str>);
63 type Return = Option<String>;
64
65 const NAME: &'static str = "getString";
66 }
67 ThisMethod::call(&self.self_, env, (key, None))
68 }
69
70 pub fn get_binary(&self, env: &mut JNIEnv, key: &str) -> JResult<Option<Vec<u8>>> {
71 let Some(b64) = self.get_string(env, key)? else {
72 return Ok(None);
73 };
74
75 Ok(match BASE64_STANDARD.decode(&b64) {
76 Ok(data) => Some(data),
77 Err(e) => {
78 tracing::error!(%e, "Error decoding base64 data, ignoring value");
79 tracing::debug!(?e, ?b64);
80 None
81 }
82 })
83 }
84
85 pub fn edit(&self, env: &mut JNIEnv) -> JResult<SharedPreferencesEditor> {
86 struct ThisMethod;
87 impl Method for ThisMethod {
88 type Param = NoParam;
89 type Return = SharedPreferencesEditor;
90
91 const NAME: &str = "edit";
92 }
93 ThisMethod::call(&self.self_, env, NoParam)
94 }
95}
96
97pub struct SharedPreferencesEditor {
98 self_: GlobalRef,
99}
100impl FromValue for SharedPreferencesEditor {
101 fn signature() -> SignatureComp {
102 Self::class().into()
103 }
104
105 fn from_object(self_: GlobalRef, _env: &mut JNIEnv) -> JResult<Self> {
106 Ok(Self { self_ })
107 }
108}
109impl SharedPreferencesEditor {
110 fn class() -> ClassDecl {
111 ClassDecl("Landroid/content/SharedPreferences$Editor;")
112 }
113
114 pub fn put_string(&self, env: &mut JNIEnv, key: &str, value: &str) -> JResult<Self> {
115 struct ThisMethod<'a>(PhantomData<&'a ()>);
116 impl<'a> Method for ThisMethod<'a> {
117 type Param = (&'a str, &'a str);
118 type Return = SharedPreferencesEditor;
119
120 const NAME: &'static str = "putString";
121 }
122 ThisMethod::call(&self.self_, env, (key, value))
123 }
124
125 pub fn put_binary(&self, env: &mut JNIEnv, key: &str, value: &[u8]) -> JResult<Self> {
126 let value = BASE64_STANDARD.encode(value);
127 self.put_string(env, key, &value)
128 }
129
130 pub fn remove(&self, env: &mut JNIEnv, key: &str) -> JResult<Self> {
131 struct ThisMethod<'a>(PhantomData<&'a ()>);
132 impl<'a> Method for ThisMethod<'a> {
133 type Param = &'a str;
134 type Return = SharedPreferencesEditor;
135
136 const NAME: &'static str = "remove";
137 }
138 ThisMethod::call(&self.self_, env, key)
139 }
140
141 pub fn commit(&self, env: &mut JNIEnv) -> JResult<bool> {
142 struct ThisMethod;
143 impl Method for ThisMethod {
144 type Param = NoParam;
145 type Return = bool;
146
147 const NAME: &str = "commit";
148 }
149 ThisMethod::call(&self.self_, env, NoParam)
150 }
151}