Android Question KeyValueStore2 no luck

MitchBu

Active Member
Licensed User
KVS seems to be exactly what I need. In another language, all my apps use a "dictionary" which supports all settings through key value pairs.

I am trying to implement it in a small test project.

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim Diko As KeyValueStore
End Sub
B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    Activity.LoadLayout("Main")
  
    'Initialize Diko
    If FirstTime Then
        Diko.Initialize(File.DirDefaultExternal, "datastore")
    End If
I get the error below. Apparently SQL complains that it cannot open it's database. Please forget my ignorance, I was under the impression that initialize was all that was needed. What must I do to create that SQL file ? Or is it something I left out ?

Any help will be appreciated.

TIA.


--------- beginning of system
--------- beginning of main
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
Error occurred on line: 37 (Main)
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (Sqlite code 14): Could not open database, (OS error - 2:No such file or directory)
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:223)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:207)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:511)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:194)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:183)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:880)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:864)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:767)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:742)
at anywheresoftware.b4a.sql.SQL.Initialize(SQL.java:44)
at b4a.example3.keyvaluestore._initialize(keyvaluestore.java:362)
at b4a.example.main._activity_create(main.java:394)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:351)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
at b4a.example.main.afterFirstLayout(main.java:104)
at b4a.example.main.access$000(main.java:17)
at b4a.example.main$WaitForLayout.run(main.java:82)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7529)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)

** Activity (main) Resume **
 

MitchBu

Active Member
Licensed User
You might want to take a look at the tutorial for this class.
I followed it and found it very helpful, especially the sample app.
https://www.b4x.com/android/forum/threads/b4x-keyvaluestore-2-simple-powerful-local-datastore.63633/

-j
I will for sure study it in detail tomorrow. But, since obviously you are using that class, can you please confirm there is no need to crate the database beforehand, and that the initialize command suffices ?

Thank you in advance.
 

jimmyF

Active Member
Licensed User
there is no need to crate the database beforehand, and that the initialize command suffices ?
That's it, exactly. Just give the db a name when initializing the class instance. And best to declare the class, " Public kvs As KeyValueStore ", and do the initialzation in the Starter service module.
Very important! Be sure, of course, that you have the correct permissions for the directory in which you create the db, as mentioned by @Computersmith64.
 

Erel

Administrator
Staff member
Licensed User
Several mistakes:

1. Best to use File.DirInternal.
2. Never use File.DirDefaultExternal.
3. You can use Runtime.GetSafeDirDefaultExternal though option #1 is better.
4. Only use Sub Globals for UI related objects. You should declare 'diko' in Process_Globals or better in Process_Globals of the starter service (and initialize it in Service_Create).
 

MitchBu

Active Member
Licensed User
Thank you jimmyF and Erel. With your help, I was able to make it work :)

I could not declare and initialize in the Starter service, diko was not available in Main. So I declare and initiliaze in Main, that works just fine.

I post what I did so someone searching later will have the solution.

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
       Public Diko As KeyValueStore
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("Layout1")
    Activity.LoadLayout("Main")
   
    'Initialize value pairs
    If FirstTime Then
        Diko.Initialize(File.DirInternal, "datastore")
    End If
I had thought of using Map, but I did not see where to save it when the app quits. With kvs, I won't have to worry about that.
 
Top