Android Question B4XPages- is not Friendly when Using SQLite with RunTImePermissions for Storing in DirRootExternal

Status
Not open for further replies.

Mahares

Expert
Licensed User
Longtime User
I can use DirInternal without RunTimePermissions (rtp) or SafeDefaultExternal folder with rtp without any problems with B4XPages. But, when I request permission and try to use it with DirRootExternal folder, it seems that problems pop up and the app crashes. To illustrate the problem, I have attached a complete project using a scaled back and stripped down B4XPages klaus SQLiteLight2 example to focus in the problem at hand.

I really need to have access to DirRootExternal because a few of my apps use it and I am sure thousands of forum developers use it because it is practical for many reasons cited by developers in the forum.

I hope many of you can download the project and see for yourselves. Perhaps, some of you could point where changes in my code need be made to make it work. To make B4XPages succeed we have to make it possible with rtp and external storage.

I even put the rtp request code in Starter service and in Main, but it did not help solve the crash. I also implemented Wait For to allow for permission to be granted first, but to no avail.

B4X:
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
Error occurred on line: 66 (B4XMainPage)
java.lang.RuntimeException: Object should first be initialized.
at anywheresoftware.b4a.sql.SQL.checkNull(SQL.java:55)
at anywheresoftware.b4a.sql.SQL.ExecQuery(SQL.java:210)
at b4a.example.b4xmainpage._showtable(b4xmainpage.java:86)
at b4a.example.b4xmainpage._b4xpage_appear(b4xmainpage.java:55)
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 anywheresoftware.b4a.BA$2.run(BA.java:387)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857)
 

Attachments

  • B4XPages_SQLiteLight2ModifiedbyMahares.zip
    11.4 KB · Views: 182

Erel

B4X founder
Staff member
Licensed User
Longtime User
This is really not the way to post a question or feedback. Start with asking the question. Why post the wrong conclusions before you know the answer? You are misleading other members.
Handling runtime permissions in B4XPages projects is as simple as handling them in non-B4XPages projects.

Your template code is wrong.

Start here: [B4X] B4XPages - Cross platform and simple framework for managing multiple pages
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Handling runtime permissions in B4XPages projects is as simple as handling them in non-B4XPages projects.
I think you completely misunderstood the thread objective. It was a question, not conclusion. I could not run the project with rtp. I needed someone to tell me where the problem is. It is nothing against B4Xpages. I like it. I have read your tutorial. I have been spending days on this issue. As I mentioned, I have no problem with DirInternal or SafeDirectoryExternal. I cannot believe, you are annoyed with such thread. It is a valid and legitimate thread. You always say, try and if you are stuck, post.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
You are missing this in Main. Perhaps you deleted it by accident.
Sub Activity_PermissionResult (Permission As String, Result As Boolean)
B4XPages.Delegate.Activity_PermissionResult(Permission, Result)
End Sub

Otherwise there are timing/ missing initialisation errors. This works but should be reorganised for the real app.
B4X:
Private Sub B4XPage_Appear
    DBFilePath=File.DirRootExternal
    #If B4J
    SQL1.InitializeSQLite(xui.DefaultFolder, "persons.db", True)
    #Else
    SQL1.Initialize(DBFilePath, "persons.db", True)
    #End If
    bxtTable.Initialize(Me, "")
    InitTable
    ShowTable
End Sub
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
bxtTable.Initialize(Me, "")
How did that line work for you. The B4Xtable was added via the Designer. It should not be initialized. I made the changes you requested, but still no go. I can either upload the project again with your changes or you may export yours that worked for you in case I have missed something else and I will test and implement.
 
Upvote 0

rraswisak

Active Member
Licensed User
Longtime User
@Mahares please try modified you code with this;

Add missing sub in Main as @agraham sugested
B4X:
Sub Activity_PermissionResult (Permission As String, Result As Boolean)
    B4XPages.Delegate.Activity_PermissionResult(Permission, Result)
End Sub

Check permission if already granted or not
B4X:
Private Sub B4XPage_Created (Root1 As B4XView)
    
    If rp.Check(rp.PERMISSION_READ_EXTERNAL_STORAGE) = False Then
        rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
        wait for B4XPage_PermissionResult(Permision As String, Result As Boolean)
        If Result = False Then
            MsgboxAsync("No permission to access external storage", "")
            Return
        Else
            Log("Permission granted")
        End If
    End If 
    ...
    ...
End Sub
and make sure only show data when you have permission
B4X:
Private Sub B4XPage_Appear
    If rp.Check(rp.PERMISSION_READ_EXTERNAL_STORAGE) = True Then ShowTable    
End Sub
 
Upvote 0

Mahares

Expert
Licensed User
Longtime User
Try this.
It is still not working even with your project. If you tested and worked for you Andrew, then I compliment you. I cannot get it to work with this line or without.
bxtTable.Initialize(Me, "")

Private Sub B4XPage_Appear If rp.Check(rp.PERMISSION_READ_EXTERNAL_STORAGE) = True Then ShowTable End Sub

@rraswisak:
Did you actually test it with your suggestion? I implemented your above suggestion. I started with a fresh app after I deleted the old B4X Example app and persons.db. It runs the initial IDE run, but when you run it subsequent times from IDE, it crashes. Instead of posting a bunch or error logs for you, here is the revised project again if you or someone else want to test and see what is wrong. .
 

Attachments

  • B4XPages_SQLiteLight2070520.zip
    11.5 KB · Views: 157
Upvote 0

Mahares

Expert
Licensed User
Longtime User
you don't even make change in the B4XPage_Created event as i suggested above..
Your suggestions work well if I do not close the database with SQL1.Close upon exit, but crashes if I attempt to close it and reconnect and run the app again:
B4X:
Private Sub B4XPage_CloseRequest As ResumableSub
    Dim sf As Object = xui.Msgbox2Async("Do you want to quit ?", "Quit", "Yes", "Cancel", "No", Null)
    Wait For (sf) Msgbox_Result (Result As Int)
    If Result = xui.DialogResponse_Positive Then
        SQL1.Close  'this is where it crashes if I add this line, unless I comment it.
        Return True
    End If
    Return False
End Sub
I have attached the project again, this time where I attempt to close the database when exit. I need to close it, in case another app tries to access the same database.
 

Attachments

  • B4XPages_SQLiteLight2_rraswisak.zip
    11.5 KB · Views: 187
Upvote 0

rraswisak

Active Member
Licensed User
Longtime User
Calling SQL1.Close will release all reference to the database connection that cause the new problem, while B4XPage_CloseRequest only close the B4XPage it self but not the whole app (cmiiw). So your B4XPage_CloseRequest event above only close (hide) the app but actually still work in background.

To get this work, i would suggest you change Return True with ExitApplication

B4X:
Private Sub B4XPage_CloseRequest As ResumableSub
    Dim sf As Object = xui.Msgbox2Async("Do you want to quit ?", "Quit", "Yes", "Cancel", "No", Null)
    Wait For (sf) Msgbox_Result (Result As Int)
    If Result = xui.DialogResponse_Positive Then
        SQL1.Close  'this is where it crashes if I add this line, unless I comment it.
        'Return True
        ExitApplication
    End If
    Return False
End Sub
 
Upvote 0
Status
Not open for further replies.
Top