Android Tutorial KeyValueStore class - Simple and efficient key/value data store

Discussion in 'Tutorials & Examples' started by Erel, Feb 13, 2013.

Thread Status:
Not open for further replies.
  1. Erel

    Erel Administrator Staff Member Licensed User

    KeyValueStore v2 is available here: https://www.b4x.com/android/forum/threads/b4x-keyvaluestore-2-simple-powerful-local-datastore.63633/

    In many cases applications need to store all kinds of data.

    Key / value data stores (sometimes referred as NoSQL) can offer an alternative to relational databases (SQL). The key / value store offers a simple functionality. It allows you to store all kinds of values, where each value is mapped to a key. Very similar to Maps (as well as Dictionary, Hashtable, HashMap...). The main difference is that the store is persisted in the file system.

    KeyValueStore class uses an SQLite database to store and retrieve all kinds of values.

    It uses RandomAccessFile.WriteObject or WriteEncryptedObject to save collections and user types.

    Using KeyValueStore is similar to using a Map:
    Code:
    Sub Process_Globals
       
    Private kvs As KeyValueStore
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
       
    If FirstTime Then
          kvs.Initialize(
    File.DirDefaultExternal, "datastore")
       
    End If
       
    'put a "simple" value
       kvs.PutSimple("time"DateTime.Now)
       
    'fetch this value
       Log(DateTime.Time(kvs.GetSimple("time")))

       
    'put a Bitmap
       kvs.PutBitmap("bitmap1"LoadBitmap(File.DirAssets, "asteroids.png"))
       
    'fetch a bitmap
       Activity.SetBackgroundImage(kvs.GetBitmap("bitmap1"))

       
    'remove the bitmap from the store
       kvs.Remove("bitmap1")

       
    'add a collection
       Dim list1 As List
       list1.Initialize
       
    For i = 1 To 10
          list1.Add(
    "Item #" & i)
       
    Next
       kvs.PutObject(
    "list1", list1)

       
    'fetch the collection
       Dim list2 As List = kvs.GetObject("list1")
       
    Log(list2)
       
    'encrypt the list
       kvs.PutEncyptedObject("encrypted list", list1, "topsecret")
       
    Try
          
    'note that if you run this example in Debug then it will break on this call. Press F5 to continue...
          list2 = kvs.GetEncryptedObject("encrypted list""wrong password")
       
    Catch
          
    Log("Wrong password!")
       
    End Try
       list2 = kvs.GetEncryptedObject(
    "encrypted list""topsecret")
       
    Log(list2)
    End Sub
    The public methods of KeyValueStore:
    Code:
    'Puts a simple value in the store.
    'Strings and number types are considered "simple" values.
    Sub PutSimple(Key As String, Value As Object) As Boolean

    'Puts an object in the store. This method uses RandomAccessFile.WriteObject to save the object in the store.
    'It is capable of writing the following types of objects: Lists, Arrays, Maps, Strings, primitive types and user defined types.
    'Combinations of these types are also supported. For example, a Map with several lists of arrays can be written.
    'The element type inside a collection must be a String OR primitive Type.
    Sub PutObject(Key As String, Value As Object) As Boolean

    'Similar to PutObject. Encrypts the object before writing it. Note that you can use it to store "simple" types as well.
    Sub PutEncyptedObject(Key As String, Value As Object, Password As StringAs Boolean

    'Puts a bitmap in the store.
    Sub PutBitmap(Key As String, Value As BitmapAs Boolean

    'Reads the data from the input stream and saves it in the store.
    Sub PutInputStream(Key As String, Value As InputStreamAs Boolean

    'Removes the key and value mapped to this key.
    Sub Remove(Key As String)

    'Returns a list with all the keys.
    Sub ListKeys As List

    'Tests whether a key is available in the store.
    Sub ContainsKey(Key As StringAs Boolean

    'Deletes all data from the store.
    Sub DeleteAll

    'Returns a "simple" value. See PutSimple.
    Sub GetSimple(Key As StringAs String

    'Returns an InputStream from the store. See PutInputStream.
    Sub GetInputStream(Key As StringAs InputStream

    'Returns a bitmap from the store. See PutBitmap.
    Sub GetBitmap(Key As StringAs Bitmap

    'Returns an object from the store. See PutObject.
    Sub GetObject(Key As StringAs Object

    'Returns an encrypted object from the store. See PutEncryptedObject.
    Sub GetEncryptedObject(Key As String, Password As StringAs Object

    'Closes the store.
    Sub Close
    So if you do not need the more advanced features of a relational database then KeyValueStore is your probably best solution for data persisting.

    The class is included in the attached example. It depends on the SQL and RandomAccessFile libraries.

    V1.01 - Fixes an issue with open cursors.
     

    Attached Files:

    Last edited: Feb 17, 2016
    Isac, Devv, gudino jose luis and 13 others like this.
  2. mc73

    mc73 Well-Known Member Licensed User

    Nice one!
     
  3. stefanoa

    stefanoa Active Member Licensed User

    Great!
    :sign0098:
     
  4. BPak

    BPak Active Member Licensed User

    I have Version 2.50 - Core 2.46 - RandomAccessFile 1.31 - SQL 1.20
    and running in RELEASE get the Log of "Wrong Password". Yet the program runs and prints out all the Logs...
     
  5. corwin42

    corwin42 Expert Licensed User

    If you carefully look at the example you will see that this is correct:

    Code:
    kvs.PutEncyptedObject("encrypted list", list1, "topsecret")
        
    Try
            
    'note that if you run this example in Debug then it will break on this call. Press F5 to continue...
            list2 = kvs.GetEncryptedObject("encrypted list""wrong password")
        
    Catch
            
    Log("Wrong password!")
        
    End Try
        list2 = kvs.GetEncryptedObject(
    "encrypted list""topsecret")
    The example tries to get the encrypted list with the password "wrong password" first and then tries with the correct password.
     
  6. BPak

    BPak Active Member Licensed User

    Correct. That got by me!
    Thanks.
     
  7. bluedude

    bluedude Well-Known Member Licensed User

    Avoiding exposing some unique API keys in my app.

    Hi Erel,

    I would like to use the keyvalue store but I need to store some information into it outside my app. The reason for this is secret API keys that are used for the backend.

    So I don't want to store the apikey in the app. code, any way to do this by using the keyvalue store? I assume it is just an SQLLite database?

    Cheers,
     
  8. Erel

    Erel Administrator Staff Member Licensed User

    KeyValueStore uses a regular SQLite database to store the data.

    The simplest solution is to create a program that takes the keys and writes them to a store. Then use File.Copy to copy the file from File.DirInternalCache to the sd card.

    The store file can be added to other projects (copy the file from File.DirAssets to File.DirInternalCache if it isn't already there).
     
  9. bluedude

    bluedude Well-Known Member Licensed User

    Ok, need to see if I can get that running.

    Thanks.
     
  10. Filippo

    Filippo Expert Licensed User

    Thank you!
    This is precisely the class which I need in my new app.
    :sign0098:
     
  11. IanMc

    IanMc Well-Known Member Licensed User

    I second that! Brilliant!

    :sign0142:

    I wouldnt' mind a bit of help though.

    I need to persist a couple of lists.

    In the example you save a list but then you load that list again but to a new list.

    How would you save a list and then load it back again? The same list?
     
    Last edited: Feb 26, 2013
  12. Erel

    Erel Administrator Staff Member Licensed User

    Not sure that I understand. You can just assign the returned list to the original variable.
     
  13. IanMc

    IanMc Well-Known Member Licensed User

    Ah, ok, sorry to be so dim :)

    So...
    Code:
    Sub Globals
       
    'These global variables will be redeclared each time the activity is created.
       'These variables can only be accessed from this module.
       Dim ListNames As List 
       ListNames.Initialize
    End Sub

    Sub Activity_Create(FirstTime As Boolean)
       
    'Do not forget to load the layout file created with the visual designer. For example:
       Activity.LoadLayout("main")
    Dim ListNames2 As List = Main.kvs.GetObject("Names")
    ListNames = ListNames2


    End Sub
    Something like that?
     
    Watchkido1 likes this.
  14. Erel

    Erel Administrator Staff Member Licensed User

    Your code is fine.
    Though this code is also fine (and logically the same):
    Code:
    Sub Activity_Create(FirstTime As Boolean)
        
    'Do not forget to load the layout file created with the visual designer. For example:
        Activity.LoadLayout("main")
    ListNames = Main.kvs.GetObject(
    "Names")
    End Sub
     
    Watchkido1 likes this.
  15. IanMc

    IanMc Well-Known Member Licensed User

    Thanks Erel!

    I've been having a play with KeyValueStore, its really good!

    I can see this becoming a valuable tool in my toolbox.

    Cheers!

    :)
     
  16. dgoss

    dgoss Member Licensed User

    can keyvaluestore be manually edited, only ask cause i need to change a wrong value. its sposed to be in defaultexternal under "datastore" but dont see it:sign0104:
     
  17. Erel

    Erel Administrator Staff Member Licensed User

    The data is saved in a SQLite file in:
    Code:
    Private tempFolder = File.DirInternalCache, tempFile = "key_value_temp.dat" As String
     
    Watchkido1 likes this.
  18. Quaki

    Quaki Member Licensed User

    Hi
    I'm trying to do this
    But I dont know how :( Erel could you write short sample how to export this file on the example from post one and then import it to other aplication
    Quaki
     
  19. Erel

    Erel Administrator Staff Member Licensed User

    Do you want to manually add some data to the store (before the app runs)?
     
  20. Quaki

    Quaki Member Licensed User

    Hi
    Yes thats exactly what I want to do I even create something like this
    Code:
    Sub Process_Globals
    Private kvs As KeyValueStore
    Dim al As String
    Dim al1 As String      
    Dim al2 As String
    Dim al3 As String


    End Sub

    Sub Globals

    End Sub

    Sub Activity_Create(FirstTime As Boolean)
       
    If FirstTime Then
          kvs.Initialize(
    File.DirDefaultExternal, "datastore")
       
    End If
       
       al = 
    "0"
       al1 = 
    "0"
       al2 = 
    "0"
       al3 = 
    "0"
       
       
       kvs.PutSimple(
    "al""al")
       kvs.PutSimple(
    "al1""al1")
       kvs.PutSimple(
    "al2""al2")
        kvs.PutSimple(
    "al3""al3")
        

    File.Copy(??????)


    End Sub

    Sub Activity_Resume

    End Sub

    Sub Activity_Pause (UserClosed As Boolean)
    but I do not know what shoud be in place of (????) to export file into Sd card or any other folder and how to import file before the target aplication starts (or how to load file on first start of target aplication )
    Quaki
     
    Last edited: Jun 19, 2013
Thread Status:
Not open for further replies.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice