94aac592d660be4fffdd3470cbabfaa9d7ae200f
[nit.git] / lib / android / shared_preferences / shared_preferences_api10.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Copyright 2014 Frédéric Vachon <fredvac@gmail.com>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Services to save/load data using `android.content.SharedPreferences` for the android platform
18 module shared_preferences_api10
19
20 import native_app_glue
21 import serialization
22 private import json_serialization
23
24 in "Java" `{
25 import android.content.SharedPreferences;
26 import android.content.Context;
27 import android.app.Activity;
28 import java.util.Map;
29 import java.util.Iterator;
30 import java.lang.ClassCastException;
31 import java.lang.NullPointerException;
32 `}
33
34 extern class NativeSharedPreferences in "Java" `{ android.content.SharedPreferences `}
35 super JavaObject
36
37 fun contains(key: JavaString): Bool in "Java" `{ return recv.contains(key); `}
38 fun get_all: HashMap[JavaString, JavaObject] import HashMap[JavaString, JavaObject],
39 HashMap[JavaString, JavaObject].[]= in "Java" `{
40 Map<String, ?> java_map = null;
41 int nit_hashmap = new_HashMap_of_JavaString_JavaObject();
42 try {
43 java_map = recv.getAll();
44 } catch (NullPointerException e) {
45 return nit_hashmap;
46 }
47
48 for (Map.Entry<String, ?> entry: java_map.entrySet())
49 HashMap_of_JavaString_JavaObject__index_assign(nit_hashmap,
50 entry.getKey(), entry.getValue());
51
52 return nit_hashmap;
53 `}
54 fun get_boolean(key: JavaString, def_value: Bool): Bool in "Java" `{
55 boolean return_value;
56 try {
57 return_value = recv.getBoolean(key, def_value);
58 } catch (ClassCastException e) {
59 return def_value;
60 }
61
62 return return_value;
63 `}
64 fun get_float(key: JavaString, def_value: Float): Float in "Java" `{
65 float return_value;
66 try {
67 return_value = recv.getFloat(key, (float) def_value);
68 } catch (ClassCastException e) {
69 return def_value;
70 }
71
72 return return_value;
73 `}
74 fun get_int(key: JavaString, def_value: Int): Int in "Java" `{
75 int return_value;
76 try {
77 return_value = recv.getInt(key, (int)def_value);
78 } catch (ClassCastException e) {
79 return def_value;
80 }
81
82 return return_value;
83 `}
84 fun get_long(key: JavaString, def_value: Int): Int in "Java" `{
85 long return_value;
86 try {
87 return_value = recv.getLong(key, def_value);
88 } catch (ClassCastException e) {
89 return def_value;
90 }
91
92 return (int) return_value;
93 `}
94 fun get_string(key: JavaString, def_value: JavaString): JavaString in "Java" `{
95 String return_value = null;
96 try {
97 return_value = recv.getString(key, def_value);
98 } catch (ClassCastException e) {
99 return def_value;
100 }
101
102 return return_value;
103 `}
104
105 # HACK for bug #845
106 redef fun new_global_ref import sys, Sys.jni_env `{
107 Sys sys = NativeSharedPreferences_sys(recv);
108 JNIEnv *env = Sys_jni_env(sys);
109 return (*env)->NewGlobalRef(env, recv);
110 `}
111 end
112
113 extern class NativeSharedPreferencesEditor in "Java" `{ android.content.SharedPreferences$Editor `}
114 super JavaObject
115
116 fun clear: NativeSharedPreferencesEditor in "Java" `{ return recv.clear(); `}
117 fun commit: Bool in "Java" `{ return recv.commit(); `}
118 fun put_boolean(key: JavaString, value: Bool ): NativeSharedPreferencesEditor in "Java" `{
119 return recv.putBoolean (key, value);
120 `}
121 fun put_float(key: JavaString, value: Float): NativeSharedPreferencesEditor in "Java" `{
122 return recv.putFloat(key, (float) value);
123 `}
124 fun put_int(key: JavaString, value: Int): NativeSharedPreferencesEditor in "Java" `{
125 return recv.putInt(key, (int)value);
126 `}
127 fun put_long(key: JavaString, value: Int): NativeSharedPreferencesEditor in "Java" `{
128 return recv.putLong(key, value);
129 `}
130 fun put_string(key: JavaString, value: JavaString): NativeSharedPreferencesEditor in "Java" `{
131 return recv.putString(key, value);
132 `}
133 fun remove(key: JavaString): NativeSharedPreferencesEditor in "Java" `{
134 return recv.remove(key);
135 `}
136
137 # HACK for bug #845
138 redef fun new_global_ref import sys, Sys.jni_env `{
139 Sys sys = NativeSharedPreferencesEditor_sys(recv);
140 JNIEnv *env = Sys_jni_env(sys);
141 return (*env)->NewGlobalRef(env, recv);
142 `}
143 end
144
145 # Provides services to save and load data for the android platform
146 class SharedPreferences
147 protected var context: NativeActivity
148 protected var shared_preferences: NativeSharedPreferences
149 protected var editor: NativeSharedPreferencesEditor
150
151 # Automatically commits every saving/removing instructions (`true` by default)
152 var auto_commit = true
153
154 protected init(app: App, file_name: String, mode: Int)
155 do
156 self.context = app.native_activity
157 sys.jni_env.push_local_frame(1)
158 setup(file_name.to_java_string, mode)
159 sys.jni_env.pop_local_frame
160 end
161
162 # Restricts file access to the current application
163 init privately(app: App, file_name: String)
164 do
165 self.init(app, file_name, private_mode)
166 end
167
168 # File access mode
169 private fun private_mode: Int in "Java" `{ return Context.MODE_PRIVATE; `}
170
171 private fun set_vars(shared_pref: NativeSharedPreferences, editor: NativeSharedPreferencesEditor)
172 do
173 self.shared_preferences = shared_pref.new_global_ref
174 self.editor = editor.new_global_ref
175 end
176
177 private fun setup(file_name: JavaString, mode: Int) import context, set_vars in "Java" `{
178 Activity context = (Activity) SharedPreferences_context(recv);
179 SharedPreferences sp;
180
181 // Uses default SharedPreferences if file_name is an empty String
182 if (file_name.equals("")) {
183 sp = context.getPreferences((int)mode);
184 } else {
185 sp = context.getSharedPreferences(file_name, (int)mode);
186 }
187
188 SharedPreferences.Editor editor = sp.edit();
189
190 SharedPreferences_set_vars(recv, sp, editor);
191 `}
192
193 private fun commit_if_auto do if auto_commit then self.commit
194
195 # Returns true if there's an entry corresponding the given key
196 fun has(key: String): Bool
197 do
198 sys.jni_env.push_local_frame(2)
199 var return_value = shared_preferences.contains(key.to_java_string)
200 sys.jni_env.pop_local_frame
201 return return_value
202 end
203
204 # Returns a `HashMap` containing all entries or `null` if there's no entries
205 #
206 # User has to manage local stack deallocation himself
207 #
208 # ~~~nitish
209 # var foo = new HashMap[JavaString, JavaObject]
210 # # ...
211 # for key, value in foo do
212 # key.delete_local_ref
213 # value.delete_local_ref
214 # end
215 # ~~~
216 # *You should use Nit getters instead and get each value one by one*
217 fun all: nullable HashMap[JavaString, JavaObject]
218 do
219 var hashmap = shared_preferences.get_all
220 if hashmap.is_empty then return null
221 return hashmap
222 end
223
224 # Returns the `Bool` value corresponding the given key or `def_value` if none
225 # or if the value isn't of correct type
226 fun bool(key: String, def_value: Bool): Bool
227 do
228 sys.jni_env.push_local_frame(2)
229 var return_value = shared_preferences.get_boolean(key.to_java_string, def_value)
230 sys.jni_env.pop_local_frame
231 return return_value
232 end
233
234 # Returns the `Float` value corresponding the given key or `def_value` if none
235 # or if the value isn't of correct type
236 fun float(key: String, def_value: Float): Float
237 do
238 sys.jni_env.push_local_frame(2)
239 var return_value = shared_preferences.get_float(key.to_java_string, def_value)
240 sys.jni_env.pop_local_frame
241 return return_value
242 end
243
244 # Returns the `Int` value corresponding the given key or `def_value` if none
245 # or if the value isn't of correct type
246 # Be aware of possible `def_value` integer overflow as the Nit `Int` corresponds
247 # to Java `long`
248 fun int(key: String, def_value: Int): Int
249 do
250 sys.jni_env.push_local_frame(2)
251 var return_value = shared_preferences.get_int(key.to_java_string, def_value)
252 sys.jni_env.pop_local_frame
253 return return_value
254 end
255
256 # Returns the `Int` value corresponding the given key or `def_value` if none
257 # or if the value isn't of correct type
258 # Calls `getLong(key, value)` java method
259 # Nit `Int` is equivalent to Java `long` so that no integer overflow will occur
260 fun long(key: String, def_value: Int): Int
261 do
262 sys.jni_env.push_local_frame(2)
263 var return_value = shared_preferences.get_long(key.to_java_string, def_value)
264 sys.jni_env.pop_local_frame
265 return return_value
266 end
267
268 # Returns the `String` value corresponding the given key or `def_value` if none
269 # or if the value isn't of correct type
270 fun string(key: String, def_value: String): String
271 do
272 sys.jni_env.push_local_frame(3)
273 var java_return_value = shared_preferences.get_string(key.to_java_string,
274 def_value.to_java_string)
275 var nit_return_value = java_return_value.to_s
276 sys.jni_env.pop_local_frame
277 return nit_return_value
278 end
279
280 # Clears all the dictionnary entries in the specified file or the default file
281 # if none specified at instanciation
282 # Returns `self` allowing fluent programming
283 fun clear: SharedPreferences
284 do
285 editor.clear
286 commit_if_auto
287 return self
288 end
289
290 # If auto_commit is `false`, has to be called to save the data to persistant memory
291 fun commit: Bool
292 do
293 sys.jni_env.push_local_frame(1)
294 var return_value = editor.commit
295 sys.jni_env.pop_local_frame
296 return return_value
297 end
298
299 # Set a key-value pair using a `Bool` value
300 # Returns `self` allowing fluent programming
301 fun add_bool(key: String, value: Bool ): SharedPreferences
302 do
303 sys.jni_env.push_local_frame(1)
304 editor.put_boolean(key.to_java_string, value)
305 sys.jni_env.pop_local_frame
306 commit_if_auto
307 return self
308 end
309
310 # Set a key-value pair using a `Float` value
311 # Returns `self` allowing fluent programming
312 #
313 # Be aware of possible loss of precision as Nit `Float` corresponds to Java `double`
314 # and the methods stores a Java `float`
315 fun add_float(key: String, value: Float): SharedPreferences
316 do
317 sys.jni_env.push_local_frame(1)
318 editor.put_float(key.to_java_string, value)
319 sys.jni_env.pop_local_frame
320 commit_if_auto
321 return self
322 end
323
324 # Set a key-value pair using a `Int` type value
325 # Returns `self` allowing fluent programming
326 #
327 # Be aware of possible integer overflow as the Nit `Int` corresponds to Java `long`
328 # and the methods stores a Java `int`
329 # *You might want to use add_long instead*
330 fun add_int(key: String, value: Int): SharedPreferences
331 do
332 sys.jni_env.push_local_frame(1)
333 editor.put_int(key.to_java_string, value)
334 sys.jni_env.pop_local_frame
335 commit_if_auto
336 return self
337 end
338
339 # Set a key-value pair using a `Int` type value
340 # Returns `self` allowing fluent programming
341 fun add_long(key: String, value: Int): SharedPreferences
342 do
343 sys.jni_env.push_local_frame(1)
344 editor.put_long(key.to_java_string, value)
345 sys.jni_env.pop_local_frame
346 commit_if_auto
347 return self
348 end
349
350 # Set a key-value pair using a `String` type value
351 # Returns `self` allowing fluent programming
352 fun add_string(key: String, value: String): SharedPreferences
353 do
354 sys.jni_env.push_local_frame(2)
355 editor.put_string(key.to_java_string, value.to_java_string)
356 sys.jni_env.pop_local_frame
357 commit_if_auto
358 return self
359 end
360
361 # Removes the corresponding entry in the file
362 # Returns `self` allowing fluent programming
363 fun remove(key: String): SharedPreferences
364 do
365 sys.jni_env.push_local_frame(1)
366 editor.remove(key.to_java_string)
367 sys.jni_env.pop_local_frame
368 commit_if_auto
369 return self
370 end
371
372 # Deallocate global references allocated by the SharedPreferences instance
373 fun destroy
374 do
375 self.shared_preferences.delete_global_ref
376 self.editor.delete_global_ref
377 end
378
379 # Store `value` as a serialized Json string
380 fun []=(key: String, value: nullable Serializable)
381 do
382 var serialized_string = new StringOStream
383 var serializer = new JsonSerializer(serialized_string)
384 serializer.serialize(value)
385
386 add_string(key, serialized_string.to_s)
387 commit_if_auto
388 end
389
390 # Retrieve an `Object` stored via `[]=` function
391 #
392 # Returns `null` if there's no serialized object corresponding to the given key
393 # Make sure that the serialized object is `auto_serializable` or that it redefines
394 # the appropriate methods. Refer to `Serializable` documentation for further details
395 fun [](key: String): nullable Object
396 do
397 var serialized_string = self.string(key, "")
398
399 if serialized_string == "" then return null
400
401 var deserializer = new JsonDeserializer(serialized_string)
402 return deserializer.deserialize
403 end
404 end
405
406 redef class App
407 fun shared_preferences: SharedPreferences is cached do
408 return new SharedPreferences.privately(self, "")
409 end
410 end