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

Status
Not open for further replies.

Shaun

Member
Licensed User
Longtime User
Is there a way to tell if an object exists in the keyvaluestore database on startup? If it doesn't already exist I would create it.


Thanks
 

Shaun

Member
Licensed User
Longtime User
*On Edit*
I got it to work. Where I save the Map to the KeyValueStore, I neglected to capitalize the first letter of the Key.
DOH!

I have most of my program finished except loading and saving the database file. I just don't know where it is. I don't know enough about the Android file system I guess. It's a pain in the butt because I have to hard code it with dummy values to test with. I can't save my map object to my device.

Do I have to create the database manually? Do I create the datastore directory manually? I'm stuck.
 
Last edited:
D

Deleted member 103

Guest
Hi Erel,

I just use this class in my app since yesterday and already have 2 error messages.

1. crash:

1. crash:

On my device works without problems.

Here is the link of my app.
 
D

Deleted member 103

Guest
Hi Erel,

here is my code:

B4X:
Sub Service_Create
    n.Initialize
    n.Icon = "icon_36_36"
    n.SetInfo(Main.AppName,"",Main)
    n.Sound = False
    n.Vibrate = False

    intRunModus.Initialize

    'Ab Version v1.08 gibt es kein "Initfile" mehr deshalb muss mit diese Variable geprüft werden.
    If File.Exists(File.DirInternal, "Initfile.ini") OR Main.kvs.ListKeys.Size > 0 Then
        CallSub(Main,"goRead_Initfile")
    Else
        CallSub(Main,"goWrite_Initfile")
    End If
    CallSub(Main,"CreateFirstStopWatch")

    Try
        'Initiallisiere beeper
        beep.Initialize
        beep.Load(File.DirAssets,"beep.mp3")
    Catch
        ToastMessageShow(LastException.Message, False)
    End Try
   
    Try
        'Mediaplayer initiallisieren
        mPlayer.Initialize2("mPlayer")
        oldVolume=phone1.GetVolume(phone1.VOLUME_MUSIC)
    Catch
        ToastMessageShow(LastException.Message, False)
    End Try
       
    Timer1.Initialize("Timer1",10)
    Timer1.Enabled = False   
End Sub

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

    Dim manager As AHPreferenceManager
    Dim screen As AHPreferenceScreen
    Dim PakageName As String = "fg.ItalyStopWatch"
    Dim AppName As String="StopWatch-4-all-Lite"
    Dim intStatus As clsStatus
    intStatus.Initialize
   
    Dim intRunModus As clsRunModus
    intRunModus.Initialize
   
    Dim strSpeedUnits As clsSpeedUnits
    strSpeedUnits.Initialize
   
    Dim intColor As clsColor
    intColor.Initialize
   
    Dim intSwimstyle As clsSchwimmgstyle
    intSwimstyle.Initialize
   
    Dim tColor As clsButtonColor
    tColor.Initialize
   
    Dim strSwimstyle(4) As String
    'Variablen für die Runde-Zeit-Berechnung
    Dim intLapDistance As Int=100
   
    'Diese Variable wird verhindert das die Externe Taste,
    'wenn gedrückt bleibt, weitere Zeichen sendet.
    Dim IsKeyVolumeDown As Boolean
    Dim IsExternKeyDown(6) As Boolean

    Dim IsTimeRelativeToLap As Boolean

    'Speichert den View's zustand
    Dim lstKeyValue As List
    Dim kvs As KeyValueStore
End Sub

But I think that this could be the problem!
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmMain")
   
    'Serveice Initiallisieren und starten
    StartService(smTimer)

    If FirstTime Then       
        'Settings-Menu
        CreatePreferenceScreen
        If manager.GetAll.Size = 0 Then
            SetDefaults
        Else If manager.GetAll.Size = 3 Then    'Ab Version 2.03 Volume-Control
            manager.setString("lstVolume",10)
            manager.SetString("txtBeepCount",10)
        End If
        intLapDistance=manager.GetString("txtLapDistance")

        smTimer.lstClock.Initialize
       
        lstKeyValue.Initialize
        kvs.Initialize(File.DirInternal, "datastore")
    End If
    ...
    ...
End Sub

The service "sptimer" would later start, or what do you think?
 
D

Deleted member 103

Guest
I've found the problem, it was due to AdMob. I only have the code now moved down and now works.

Old-Code:
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmMain")

    'Init Language-Modul
    mLang.InitLanguage

    'AdMob hinzufügen(Werbung)
    AdView1.Initialize2("AdView1","a14eef5a619dfe1",AdView1.SIZE_SMART_BANNER)
    Activity.AddView(AdView1, 0, pnlStatusleiste.Top - mBBL.GetAddViewHeight, 100%x, mBBL.GetAddViewHeight)
    AdView1.LoadAd
    AdView1.Visible=True
   
    'Serveice Initiallisieren und starten
    StartService(smTimer)

    If FirstTime Then       
        'Settings-Menu
        CreatePreferenceScreen
        If manager.GetAll.Size = 0 Then
            SetDefaults
        Else If manager.GetAll.Size = 3 Then    'Ab Version 2.03 Volume-Control
            manager.setString("lstVolume",10)
            manager.SetString("txtBeepCount",10)
        End If
        intLapDistance=manager.GetString("txtLapDistance")

        smTimer.lstClock.Initialize
       
        lstKeyValue.Initialize
        kvs.Initialize(File.DirInternal, "datastore")
    End If
    ...
    ...
End Sub

Neu Code:
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("frmMain")

    'Init Language-Modul
    mLang.InitLanguage
   
    'Serveice Initiallisieren und starten
    StartService(smTimer)

    If FirstTime Then       
        'Settings-Menu
        CreatePreferenceScreen
        If manager.GetAll.Size = 0 Then
            SetDefaults
        Else If manager.GetAll.Size = 3 Then    'Ab Version 2.03 Volume-Control
            manager.setString("lstVolume",10)
            manager.SetString("txtBeepCount",10)
        End If
        intLapDistance=manager.GetString("txtLapDistance")

        smTimer.lstClock.Initialize
       
        lstKeyValue.Initialize
        kvs.Initialize(File.DirInternal, "datastore")
    End If

    'AdMob hinzufügen(Werbung)
    AdView1.Initialize2("AdView1","a14eef5a619dfe1",AdView1.SIZE_SMART_BANNER)
    Activity.AddView(AdView1, 0, pnlStatusleiste.Top - mBBL.GetAddViewHeight, 100%x, mBBL.GetAddViewHeight)
    AdView1.LoadAd
    AdView1.Visible=True
    ...
    ...
End Sub
 

boten

Active Member
Licensed User
Longtime User
2 activities in the app.
Both activities need to store/restore maps of types using KeyValueStore
activity 1 handles a "large" (relatively speaking) amount of data
activity 2 handles a "medium" (again, relatively speaking) amount of data

What would be more "efficient" (execution-time)?
Using "large" AND "medium" in the same data store
or
Using a different store for each activity? (thus isolating each activity's data from the other activity)
 

luke2012

Well-Known Member
Licensed User
Longtime User
I trying this code :

dim KVMgr As KeyValueStore
KVMgr.Initialize(File.DirDefaultExternal, "datastore")

KVMgr.PutBitmap("test1",File.DirRootExternal,"foto.jpg")
KVMgr.GetBitmap("test1")


I got this error:

Dim buffer() As Byte = c.GetBlob2(0)
java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialclasskeyvaluestore_getbitmap (B4A line: 132)
ized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetBlob(Native Method)
at android.database.CursorWindow.getBlob(CursorWindow.java:399)
at android.database.AbstractWindowedCursor.getBlob(AbstractWindowedCursor.java:45)
at anywheresoftware.b4a.sql.SQL$CursorWrapper.GetBlob2(SQL.java:409)
at luke2012.android.lclibrary.classkeyvaluestore._getbitmap(classkeyvaluestore.java:177)
at luke2012.android.lclibrary.classsqlitemanager._loadbitmapfromdb(classsqlitemanager.java:1147)
at luke2012.android.lclibrary.main._activity_create(main.java:254)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
at luke2012.android.lclibrary.main.afterFirstLayout(main.java:89)
at luke2012.android.lclibrary.main.access$100(main.java:16)
at luke2012.android.lclibrary.main$WaitForLayout.run(main.java:74)
at android.os.Handler.handleCallback(Handler.java:730)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
 

luke2012

Well-Known Member
Licensed User
Longtime User
This is not the code you are running. kvs.PutBitmap expects two parameters. The key and the bitmap.

Hi Erel,
I attached the code that make the following error :

Dim buffer() As Byte = c.GetBlob2(0)
java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow. Make sure the Cursor is initialclasskeyvaluestore_getbitmap (B4A line: 132)
 

Attachments

  • kvs_test.zip
    5.6 KB · Views: 512

luke2012

Well-Known Member
Licensed User
Longtime User
Please upload the project (File - Export as zip). Or post the relevant code directly.

The maximum for the upload is 500kb but the project is 4mb.
I send you the project via eEmail.
 

luke2012

Well-Known Member
Licensed User
Longtime User
@Erel,
you can find the relevant code within the attached file.
 

Attachments

  • LCLibrary.zip
    10.6 KB · Views: 553
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…