404aaea261c35656861200482afbd088e20944af
[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 # Example :
209 # ~~~
210 # var foo = new HashMap[JavaString, JavaObject]
211 # # ...
212 # for key, value in foo do
213 # key.delete_local_ref
214 # value.delete_local_ref
215 # end
216 # ~~~
217 # *You should use Nit getters instead and get each value one by one*
218 fun all: nullable HashMap[JavaString, JavaObject]
219 do
220 var hashmap = shared_preferences.get_all
221 if hashmap.is_empty then return null
222 return hashmap
223 end
224
225 # Returns the `Bool` value corresponding the given key or `def_value` if none
226 # or if the value isn't of correct type
227 fun bool(key: String, def_value: Bool): Bool
228 do
229 sys.jni_env.push_local_frame(2)
230 var return_value = shared_preferences.get_boolean(key.to_java_string, def_value)
231 sys.jni_env.pop_local_frame
232 return return_value
233 end
234
235 # Returns the `Float` value corresponding the given key or `def_value` if none
236 # or if the value isn't of correct type
237 fun float(key: String, def_value: Float): Float
238 do
239 sys.jni_env.push_local_frame(2)
240 var return_value = shared_preferences.get_float(key.to_java_string, def_value)
241 sys.jni_env.pop_local_frame
242 return return_value
243 end
244
245 # Returns the `Int` value corresponding the given key or `def_value` if none
246 # or if the value isn't of correct type
247 # Be aware of possible `def_value` integer overflow as the Nit `Int` corresponds
248 # to Java `long`
249 fun int(key: String, def_value: Int): Int
250 do
251 sys.jni_env.push_local_frame(2)
252 var return_value = shared_preferences.get_int(key.to_java_string, def_value)
253 sys.jni_env.pop_local_frame
254 return return_value
255 end
256
257 # Returns the `Int` value corresponding the given key or `def_value` if none
258 # or if the value isn't of correct type
259 # Calls `getLong(key, value)` java method
260 # Nit `Int` is equivalent to Java `long` so that no integer overflow will occur
261 fun long(key: String, def_value: Int): Int
262 do
263 sys.jni_env.push_local_frame(2)
264 var return_value = shared_preferences.get_long(key.to_java_string, def_value)
265 sys.jni_env.pop_local_frame
266 return return_value
267 end
268
269 # Returns the `String` value corresponding the given key or `def_value` if none
270 # or if the value isn't of correct type
271 fun string(key: String, def_value: String): String
272 do
273 sys.jni_env.push_local_frame(3)
274 var java_return_value = shared_preferences.get_string(key.to_java_string,
275 def_value.to_java_string)
276 var nit_return_value = java_return_value.to_s
277 sys.jni_env.pop_local_frame
278 return nit_return_value
279 end
280
281 # Clears all the dictionnary entries in the specified file or the default file
282 # if none specified at instanciation
283 # Returns `self` allowing fluent programming
284 fun clear: SharedPreferences
285 do
286 editor.clear
287 commit_if_auto
288 return self
289 end
290
291 # If auto_commit is `false`, has to be called to save the data to persistant memory
292 fun commit: Bool
293 do
294 sys.jni_env.push_local_frame(1)
295 var return_value = editor.commit
296 sys.jni_env.pop_local_frame
297 return return_value
298 end
299
300 # Set a key-value pair using a `Bool` value
301 # Returns `self` allowing fluent programming
302 fun add_bool(key: String, value: Bool ): SharedPreferences
303 do
304 sys.jni_env.push_local_frame(1)
305 editor.put_boolean(key.to_java_string, value)
306 sys.jni_env.pop_local_frame
307 commit_if_auto
308 return self
309 end
310
311 # Set a key-value pair using a `Float` value
312 # Returns `self` allowing fluent programming
313 #
314 # Be aware of possible loss of precision as Nit `Float` corresponds to Java `double`
315 # and the methods stores a Java `float`
316 fun add_float(key: String, value: Float): SharedPreferences
317 do
318 sys.jni_env.push_local_frame(1)
319 editor.put_float(key.to_java_string, value)
320 sys.jni_env.pop_local_frame
321 commit_if_auto
322 return self
323 end
324
325 # Set a key-value pair using a `Int` type value
326 # Returns `self` allowing fluent programming
327 #
328 # Be aware of possible integer overflow as the Nit `Int` corresponds to Java `long`
329 # and the methods stores a Java `int`
330 # *You might want to use add_long instead*
331 fun add_int(key: String, value: Int): SharedPreferences
332 do
333 sys.jni_env.push_local_frame(1)
334 editor.put_int(key.to_java_string, value)
335 sys.jni_env.pop_local_frame
336 commit_if_auto
337 return self
338 end
339
340 # Set a key-value pair using a `Int` type value
341 # Returns `self` allowing fluent programming
342 fun add_long(key: String, value: Int): SharedPreferences
343 do
344 sys.jni_env.push_local_frame(1)
345 editor.put_long(key.to_java_string, value)
346 sys.jni_env.pop_local_frame
347 commit_if_auto
348 return self
349 end
350
351 # Set a key-value pair using a `String` type value
352 # Returns `self` allowing fluent programming
353 fun add_string(key: String, value: String): SharedPreferences
354 do
355 sys.jni_env.push_local_frame(2)
356 editor.put_string(key.to_java_string, value.to_java_string)
357 sys.jni_env.pop_local_frame
358 commit_if_auto
359 return self
360 end
361
362 # Removes the corresponding entry in the file
363 # Returns `self` allowing fluent programming
364 fun remove(key: String): SharedPreferences
365 do
366 sys.jni_env.push_local_frame(1)
367 editor.remove(key.to_java_string)
368 sys.jni_env.pop_local_frame
369 commit_if_auto
370 return self
371 end
372
373 # Deallocate global references allocated by the SharedPreferences instance
374 fun destroy
375 do
376 self.shared_preferences.delete_global_ref
377 self.editor.delete_global_ref
378 end
379
380 # Store `value` as a serialized Json string
381 fun []=(key: String, value: nullable Serializable)
382 do
383 var serialized_string = new StringOStream
384 var serializer = new JsonSerializer(serialized_string)
385 serializer.serialize(value)
386
387 add_string(key, serialized_string.to_s)
388 commit_if_auto
389 end
390
391 # Retrieve an `Object` stored via `[]=` function
392 #
393 # Returns `null` if there's no serialized object corresponding to the given key
394 # Make sure that the serialized object is `auto_serializable` or that it redefines
395 # the appropriate methods. Refer to `Serializable` documentation for further details
396 fun [](key: String): nullable Object
397 do
398 var serialized_string = self.string(key, "")
399
400 if serialized_string == "" then return null
401
402 var deserializer = new JsonDeserializer(serialized_string)
403 return deserializer.deserialize
404 end
405 end
406
407 redef class App
408 fun shared_preferences: SharedPreferences is cached do
409 return new SharedPreferences.privately(self, "")
410 end
411 end