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