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