android_native_keyring_store/
shared_preferences.rs

1use 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}