android_keyring/
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
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}