Android Question unable to open database file - KeyValueStore

Douglas Farias

Expert
Licensed User
Longtime User
Hi all
i m using the class keyvaluestore on my apps
https://www.b4x.com/android/forum/t...ple-and-efficient-key-value-data-store.26317/
and today i see this error on 3 of my apps today on Google Play Console.
Error:
android.database.sqlite.SQLiteException: unable to open database file
at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
at android.database.sqlite.SQLiteDatabase.<init>(SQLiteDatabase.java:1866)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:822)
at anywheresoftware.b4a.sql.SQL.Initialize(SQL.java:37)
at com.afina.iddesenvolvimento.keyvaluestore._initialize(keyvaluestore.java:291)
at com.afina.iddesenvolvimento.main._activity_create(main.java:513)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
at com.afina.iddesenvolvimento.main.afterFirstLayout(main.java:102)
at com.afina.iddesenvolvimento.main.access$000(main.java:17)
at com.afina.iddesenvolvimento.main$WaitForLayout.run(main.java:80)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
at dalvik.system.NativeStart.main(Native Method)
Galaxy Y (GT-S5360B) - Android 2.3.3 - 2.3.7


Thats strange, because i have the permission, my targetsdk is 20 and i check if the file is Writable
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="20"/>
AddPermission(android.permission.WRITE_EXTERNAL_STORAGE)
AddPermission(android.permission.READ_EXTERNAL_STORAGE)

Here is the code used to create the app folder and load the kvs.

B4X:
  If File.ExternalWritable Then
    Try
        target = File.DirRootExternal
        File.MakeDir(target, "afinadorviolao")
        fp = File.Combine(target,"afinadorviolao")
    Catch
        target = File.DirDefaultExternal
        File.MakeDir(target, "afinadorviolao")
        fp = File.Combine(target,"afinadorviolao")
    End Try
    Else
        target = File.DirInternal
        File.MakeDir(target, "afinadorviolao")
        fp = File.Combine(target,"afinadorviolao")
    End If


    If Not(kv.IsInitialized) Then kv.Initialize(fp, "data")

What the problem here?
this app dont have activity´s only the main.
i make a check if this IsInitialized too but dont solved the problem.

what can cause this problem?

PS: i dont made any changes on KVS class code.
 

Douglas Farias

Expert
Licensed User
Longtime User
at what point do you copy the database from the assetfolder to your target folder?
on kvs class have a function on initialize (createifnecessary), this create the db automatic if not exist.


Why don't you add a Log to know fp?
Why don't you comment the Try block to know if there is an error?

This is why i check If File.ExternalWritable
if cant make a folder change fp folder and if not is ExternalWritable make on DirInternal.


I never got problem on create folder or on this try catch, i have error only on
B4X:
If Not(kv.IsInitialized) Then kv.Initialize(fp, "data")

thats strange, if can create a folder without error, why cant create a db file? this is very low in kb too.
 
Last edited:
Upvote 0

Douglas Farias

Expert
Licensed User
Longtime User
Ok if this dont work i kill me :mad:

B4X:
    'CHECK IF DB EXIST AND CREATE
    Private bb As Boolean = False
    If File.ExternalWritable Then ' IF ExternalWritable
    
    Try
        target = File.DirRootExternal
        File.MakeDir(target, "afinadorviolao")
        fp = File.Combine(target,"afinadorviolao")
        If Not(kv.IsInitialized) Then kv.Initialize(fp, "data")
        bb = True
    Catch
        bb = False
        Log(fp)
        Log(LastException)
    End Try
    '''''''''''''''''''''''''''''''''''''''''''''''''''
    If bb = False Then
         Try
            target = File.DirDefaultExternal
            File.MakeDir(target, "afinadorviolao")
            fp = File.Combine(target,"afinadorviolao")
            If Not(kv.IsInitialized) Then kv.Initialize(fp, "data")
            bb = True
        Catch
            bb = False
            Log(fp)
            Log(LastException)
        End Try
    End If


    Else 'ELSE NOT ExternalWritable
        Try
        target = File.DirInternal
        File.MakeDir(target, "afinadorviolao")
        fp = File.Combine(target,"afinadorviolao")
        If Not(kv.IsInitialized) Then kv.Initialize(fp, "data")
            bb = True
        Catch
            bb = False
            Log(fp)
            Log(LastException)
        End Try
    
    
        If bb = False Then
            Log("DAMN THIS SHIT DEVICE, CANT CREATE ANYTHING")
            Log(fp)
        End If
    
    End If
    'END CHECK

@LucaMs what u think about this? its correct now? if yes i will upload for all apps thx
 
Upvote 0

Douglas Farias

Expert
Licensed User
Longtime User
on my first code if false create a folder on DirInternal

B4X:
If File.ExternalWritable Then
Try
target = File.DirRootExternal
File.MakeDir(target, "afinadorviolao")
fp = File.Combine(target,"afinadorviolao")
Catch
target = File.DirDefaultExternal
File.MakeDir(target, "afinadorviolao")
fp = File.Combine(target,"afinadorviolao")
End Try

Else 'IF EXTERNAL WRITABLE IS FALSE
target = File.DirInternal
File.MakeDir(target, "afinadorviolao")
fp = File.Combine(target,"afinadorviolao")
End If

If Not(kv.IsInitialized) Then kv.Initialize(fp, "data")
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
I see it now. Missed it in the original post.

I agree with Luca that you should use File.DirInternal unless you are storing large objects such as bitmaps.

The Try / Catch blocks you put are not useful. If it is not possible to write to File.DirRootExternal then it will not be possible to write to DirDefaultExternal as well.
 
Upvote 0

Douglas Farias

Expert
Licensed User
Longtime User
thx to try help, but the error continue.
today more reports and now with kvs 2.
i really dont know how to fix, i tryed @LucaMs example and now the KVS2
https://www.b4x.com/android/forum/threads/b4x-keyvaluestore-2-simple-powerful-local-datastore.63633/

Here is the code now
i m using kvs 2 and this run on starter service

here is my starter service code
B4X:
#Region  Service Attributes
    #StartAtBoot: False
    #ExcludeFromLibrary: True
#End Region

Sub Process_Globals
    Private logs As StringBuilder
    Private logcat As LogCat
    Private const emailAddress As String = "[email protected]"
    Public kvs As KeyValueStore
    Public fp,fptextos As String
End Sub

Sub Service_Create
    OpenOrCreateKVS("textreader","general_data")
    logs.Initialize
    #if RELEASE
        logcat.LogCatStart(Array As String("-v","raw","*:F","B4A:v"), "logcat")
    #end if
End Sub

Sub Service_Start (StartingIntent As Intent)

End Sub

Private Sub logcat_LogCatData (Buffer() As Byte, Length As Int)
    logs.Append(BytesToString(Buffer, 0, Length, "utf8"))
    If logs.Length > 5000 Then
        logs.Remove(0, logs.Length - 4000)
    End If
End Sub

'Return true to allow the OS default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    'wait for 500ms to allow the logs to be updated.
    Dim jo As JavaObject
    Dim l As Long = 500
    jo.InitializeStatic("java.lang.Thread").RunMethod("sleep", Array(l))
    logcat.LogCatStop
    logs.Append(StackTrace)
    Dim email As Email
    email.To.Add(emailAddress)
    email.Subject = "Crash Text Reader v20"
    email.Body = logs
    StartActivity(email.GetIntent)
    Return True
   

End Sub

Sub Service_Destroy

End Sub



Sub SmtpClient_MessageSent(Success As Boolean)
   Log(Success)
   Log(LastException)
End Sub



Sub OpenOrCreateKVS(Folder As String, FileName As String) As KeyValueStore
    Dim Dir, fp As String

    If File.ExternalWritable Then
        ' External writable - Try Root
        Dir = File.DirRootExternal
        Try
            File.MakeDir(Dir, Folder)
            fp = File.Combine(Dir, Folder)
            File.MakeDir(Dir, "text")
            fptextos = File.Combine(Dir,"text")
            kvs.Initialize(fp, FileName)
        Catch
            Log(fp)
            Log(LastException)
        End Try

        If Not(kvs.IsInitialized) Then
            ' Cannot save on DirRootExternal - Try DirDefaultExternal
            Dir = File.DirDefaultExternal
            Try
                File.MakeDir(Dir, Folder)
                fp = File.Combine(Dir, Folder)
                File.MakeDir(Dir, "text")
                fptextos = File.Combine(Dir,"text")
                kvs.Initialize(fp, FileName)
            Catch
                Log(fp)
                Log(LastException)
            End Try
        End If
       
    Else
   
        ' External not writable - Try DirInternal
        Dir = File.DirInternal
        Try
            File.MakeDir(Dir, Folder)
            fp = File.Combine(Dir, Folder)
            File.MakeDir(Dir, "text")
            fptextos = File.Combine(Dir,"text")
            kvs.Initialize(fp, FileName)
        Catch
            Log(fp)
            Log(LastException)
        End Try
    End If
   
    Return kvs
End Sub

i m using the @LucaMs example to initialize the kvs

on my main i dont need initialize anything, because starter service already made this right?

Today i got 7 reports via email
--------- beginning of /dev/log/main
~i:** Service (starter) Create **
/storage/sdcard0/textreader
(SQLiteCantOpenDatabaseException) android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
~i:** Service (starter) Start **
~i:** Activity (main) Create, isFirst = true **
~e:keyvaluestore_vv4 (java line: 51)
~e:java.lang.RuntimeException: Object should first be initialized.
~e: at anywheresoftware.b4a.sql.SQL.checkNull(SQL.java:48)
~e: at anywheresoftware.b4a.sql.SQL.ExecQuerySingleResult2(SQL.java:222)
~e: at leitor.df.texto.keyvaluestore._vv4(keyvaluestore.java:51)
~e: at leitor.df.texto.main._activity_create(main.java:439)
~e: at java.lang.reflect.Method.invokeNative(Native Method)
~e: at java.lang.reflect.Method.invoke(Method.java:515)
~e: at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
~e: at leitor.df.texto.main.afterFirstLayout(main.java:102)
~e: at leitor.df.texto.main.access$000(main.java:17)
~e: at leitor.df.texto.main$WaitForLayout.run(main.java:80)
~e: at android.os.Handler.handleCallback(Handler.java:808)
~e: at android.os.Handler.dispatchMessage(Handler.java:103)
~e: at android.os.Looper.loop(Looper.java:193)
~e: at android.app.ActivityThread.main(ActivityThread.java:5334)
~e: at java.lang.reflect.Method.invokeNative(Native Method)
~e: at java.lang.reflect.Method.invoke(Method.java:515)
~e: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
~e: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
~e: at dalvik.system.NativeStart.main(Native Method)
~e:keyvaluestore_vv4 (java line: 51)
~e:java.lang.RuntimeException: Object should first be initialized.
~e: at anywheresoftware.b4a.sql.SQL.checkNull(SQL.java:48)
~e: at anywheresoftware.b4a.sql.SQL.ExecQuerySingleResult2(SQL.java:222)
~e: at leitor.df.texto.keyvaluestore._vv4(keyvaluestore.java:51)
~e: at leitor.df.texto.main._activity_create(main.java:439)
~e: at java.lang.reflect.Method.invokeNative(Native Method)
~e: at java.lang.reflect.Method.invoke(Method.java:515)
~e: at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
~e: at leitor.df.texto.main.afterFirstLayout(main.java:102)
~e: at leitor.df.texto.main.access$000(main.java:17)
~e: at leitor.df.texto.main$WaitForLayout.run(main.java:80)
~e: at android.os.Handler.handleCallback(Handler.java:808)
~e: at android.os.Handler.dispatchMessage(Handler.java:103)
~e: at android.os.Looper.loop(Looper.java:193)
~e: at android.app.ActivityThread.main(ActivityThread.java:5334)
~e: at java.lang.reflect.Method.invokeNative(Native Method)
~e: at java.lang.reflect.Method.invoke(Method.java:515)
~e: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
~e: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
~e: at dalvik.system.NativeStart.main(Native Method)
--------- beginning of /dev/log/system
~i:** Service (starter) Create **
/storage/sdcard0/textreader
(SQLiteCantOpenDatabaseException) android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
~i:** Service (starter) Start **
~i:** Activity (main) Create, isFirst = true **
~e:keyvaluestore_vv4 (java line: 51)
~e:java.lang.RuntimeException: Object should first be initialized.
~e: at anywheresoftware.b4a.sql.SQL.checkNull(SQL.java:48)
~e: at anywheresoftware.b4a.sql.SQL.ExecQuerySingleResult2(SQL.java:222)
~e: at leitor.df.texto.keyvaluestore._vv4(keyvaluestore.java:51)
~e: at leitor.df.texto.main._activity_create(main.java:439)
~e: at java.lang.reflect.Method.invokeNative(Native Method)
~e: at java.lang.reflect.Method.invoke(Method.java:515)
~e: at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
~e: at leitor.df.texto.main.afterFirstLayout(main.java:102)
~e: at leitor.df.texto.main.access$000(main.java:17)
~e: at leitor.df.texto.main$WaitForLayout.run(main.java:80)
~e: at android.os.Handler.handleCallback(Handler.java:808)
~e: at android.os.Handler.dispatchMessage(Handler.java:103)
~e: at android.os.Looper.loop(Looper.java:193)
~e: at android.app.ActivityThread.main(ActivityThread.java:5334)
~e: at java.lang.reflect.Method.invokeNative(Native Method)
~e: at java.lang.reflect.Method.invoke(Method.java:515)
~e: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
~e: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
~e: at dalvik.system.NativeStart.main(Native Method)
java.lang.RuntimeException: Object should first be initialized.
at anywheresoftware.b4a.sql.SQL.checkNull(SQL.java:48)
at anywheresoftware.b4a.sql.SQL.ExecQuerySingleResult2(SQL.java:222)
at leitor.df.texto.keyvaluestore._vv4(keyvaluestore.java:51)
at leitor.df.texto.main._activity_create(main.java:439)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
at leitor.df.texto.main.afterFirstLayout(main.java:102)
at leitor.df.texto.main.access$000(main.java:17)
at leitor.df.texto.main$WaitForLayout.run(main.java:80)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5334)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:829)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:645)
at dalvik.system.NativeStart.main(Nati
ve Method)


whats the error now? i m using try catch on starter service.
thx again
 
Upvote 0

Douglas Farias

Expert
Licensed User
Longtime User
i need this folder public, and easy to find the saved text´s with another tools, like file explorer, es file explorer etc...
i can use the dirinternal but this first i need understand this error.

have a delay when start the kvs2 via starter service?
java.lang.RuntimeException: Object should first be initialized.

The error above its because the kvs2 on starter service have a delay to initialize or because the kvs cant initialize on the folders?
 
Upvote 0
Top