Android Question B4A v9.90 problem with Permissions/FusedLocationProvider

davemorris

Active Member
Licensed User
Longtime User
Hi, Guys -
Just downloaded B4A v9.90 and now I have a problem with some code that ran without problems on previous versions.

Program hangs in the this code.

This code hangs at line #17.:
Public Sub SelectCentre
    RestartDisplayNewLocationTimer
    If mLocator.IsInitialized Then ' Help to handle the bug #0180 Starting GPS
        mLocator.Disconnect
    End If
    Log("Checking fine location permission...")
    Dim perms As RuntimePermissions'
    If perms.Check(perms.PERMISSION_ACCESS_FINE_LOCATION) = False Then
        Dim msg As String = "This App will ask permission to use your device's location." & CRLF & _
        "This information is used within the App to find local centres or to check you are in the centre." & CRLF & _
        "It is not disclosed to any third parties!" & CRLF & CRLF & _
        "THE APP CANNOT RUN WITHOUT YOU ALLOWING LOCATION"
        xui.MsgboxAsync( msg, "Location permission")
        wait for MsgBox_result(resultPermission As Int)
    End If
    perms.CheckAndRequest(perms.PERMISSION_ACCESS_FINE_LOCATION)
    Wait For Activity_PermissionResult(permission As String, result As Boolean) ' <- hangs HERE!
    If result Then ' Permission has been granted to use the location services
        Log("Fine location permission OK. Connecting to location services...")
        StartLocationService
        mLocator.Connect ' This will then be handled in either mLocator_ConnectionSuccess() or mLocator_ConnectionFailed()
    Else ' Location permission has been denied
        xui.MsgboxAsync("The fine location permission has been denied. All centres will now be displayed.", "Cannot Get Location")
        DisplayAllCentres
    End If
End Sub


It may help the variable mLocator definition is in the Class_Globals

mLocator definition:
    Private mLocator As FusedLocationProvider     ' Object used to get the phone's location.

Log entries Just before it hangs

Log entries prior to App Hanging:
Checking fine location permission...
Object context is paused. Ignoring CallSubDelayed: JobDone
** Activity (aselectplaycentre2) Pause, UserClosed = false **


Like I said above, the App run OK on previous versions of B4A (going back to about 2017). Not sure if its the RunTimePermissions, FusedLocationProvider or MY MISTAKE!

Any suggestions

Kind regards
Dave Morris
 

Alex_197

Well-Known Member
Licensed User
Longtime User
Hi, Guys -
Just downloaded B4A v9.90 and now I have a problem with some code that ran without problems on previous versions.

Program hangs in the this code.

This code hangs at line #17.:
Public Sub SelectCentre
    RestartDisplayNewLocationTimer
    If mLocator.IsInitialized Then ' Help to handle the bug #0180 Starting GPS
        mLocator.Disconnect
    End If
    Log("Checking fine location permission...")
    Dim perms As RuntimePermissions'
    If perms.Check(perms.PERMISSION_ACCESS_FINE_LOCATION) = False Then
        Dim msg As String = "This App will ask permission to use your device's location." & CRLF & _
        "This information is used within the App to find local centres or to check you are in the centre." & CRLF & _
        "It is not disclosed to any third parties!" & CRLF & CRLF & _
        "THE APP CANNOT RUN WITHOUT YOU ALLOWING LOCATION"
        xui.MsgboxAsync( msg, "Location permission")
        wait for MsgBox_result(resultPermission As Int)
    End If
    perms.CheckAndRequest(perms.PERMISSION_ACCESS_FINE_LOCATION)
    Wait For Activity_PermissionResult(permission As String, result As Boolean) ' <- hangs HERE!
    If result Then ' Permission has been granted to use the location services
        Log("Fine location permission OK. Connecting to location services...")
        StartLocationService
        mLocator.Connect ' This will then be handled in either mLocator_ConnectionSuccess() or mLocator_ConnectionFailed()
    Else ' Location permission has been denied
        xui.MsgboxAsync("The fine location permission has been denied. All centres will now be displayed.", "Cannot Get Location")
        DisplayAllCentres
    End If
End Sub


It may help the variable mLocator definition is in the Class_Globals

mLocator definition:
    Private mLocator As FusedLocationProvider     ' Object used to get the phone's location.

Log entries Just before it hangs

Log entries prior to App Hanging:
Checking fine location permission...
Object context is paused. Ignoring CallSubDelayed: JobDone
** Activity (aselectplaycentre2) Pause, UserClosed = false **


Like I said above, the App run OK on previous versions of B4A (going back to about 2017). Not sure if its the RunTimePermissions, FusedLocationProvider or MY MISTAKE!

Any suggestions

Kind regards
Dave Morris
I'm suggesting you to ask for permissions on your app start, I mean on first activity create event. Add to Starter Process Global this line Public rp As RuntimePermissions

and then on Activity Create
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")

    Try
        
        SetPermission
        
        
        
    Catch
        Log(LastException)
    End Try

End Sub

Private Sub SetPermission
    
    
    Try
        For Each permission As String In Array( Starter.rp.PERMISSION_WRITE_EXTERNAL_STORAGE, _
            Starter.rp.PERMISSION_READ_EXTERNAL_STORAGE, _           
            Starter.rp.PERMISSION_READ_PHONE_STATE)           
            
            Starter.rp.CheckAndRequest(permission)
            
            Wait For Activity_PermissionResult (permission As String, Result As Boolean)
            
            If Result = False Then
                ToastMessageShow("No permission!", True)
                Activity.finish
                Return
            End If
        Next
        
        'we have permission!
        Log(GetDeviceId)
        
        
        
    Catch
        Log("SetPermission " & LastException)
    
    End Try
    
End Sub
 
Upvote 0

davemorris

Active Member
Licensed User
Longtime User
Hi Guys (and thanks to Alex_197)
After a lot of wasted time rewriting the code related to fusedlocationprovider. I should have gone straight for the permission checking code (at line#17).

B4X:
Wait For Activity_PermissionResult(permission As String, result As Boolean)
Where it was hanging.
It appears Alex_197 had the right idea - the code should be moved to the Activity module.

I fixed it by simply removing the permission checking code from the sub SelectCentre() in a class module and placing it in a sub contained in the Activity module (in my case Activity_Resume()) - which worked. Also tried the original code with the New B4A Beta V10 which it hung again (and fixed in the same manner).

Alex_197 also suggested
Add to Starter Process Global this line Public rp As RuntimePermissions
I found that RuntimePermissions could be a local variable, and it still works OK.

Beware: I do believe there is a problem in the way I was using Activity_PermissionResult() in a class module which relates only to B4A v9.9+ .

Regards
Dave
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
(in my case Activity_Resume())

It's not a good place. It will check for permission every time you open this activity.
Better to put it into Activity_Created sub.
It might be Ok to use the RuntimePermissions as a Local variable but again - it's better to ask / check for permission in the app start then in the middle of the process.
 
Upvote 0

davemorris

Active Member
Licensed User
Longtime User
Hi
I would agree about
Better to put it into Activity_Created sub.
Its a good point - also I would agree in general.
it's better to ask / check for permission in the app start then in the middle of the process.

However in my case the app does not need Location to run and the user (via an intent or using the settings) could change the location settings at any time.

However; I believe regardless of how you do it, and for what reasons, a piece of code (with a few exceptions) should work anywhere in a programme and certainly if it has been moved to a class to improve the structure and/or help create common code for B4X applications.

Regards
Dave
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
it's better to ask / check for permission in the app start then in the middle of the process.
I don't agree. It is best to ask for the permission right before your app needs it.

Activity_PermissionResult is an activity event so it will be raised in the activity, however once you switch to B4XPages (and you should) then you can handle it inside the page class with B4XPage_PermissionResult.
 
Upvote 0

Alex_197

Well-Known Member
Licensed User
Longtime User
I don't agree. It is best to ask for the permission right before your app needs it.

Activity_PermissionResult is an activity event so it will be raised in the activity, however once you switch to B4XPages (and you should) then you can handle it inside the page class with B4XPage_PermissionResult.
Why ask / check for permission in the app start is no good? I checked / asked for permissions at the very beginning right after the first start (I mean right after the app was installed) and don't bother user with it anymore. Of course I'm checking for permission every time the app starts but once the all permissions are granted user won't be bothered during the work with the app.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
and don't bother user with it anymore
1. This statement is wrong. The user will only see the permission dialog once (assuming it was approved).
2. A user opens an app, doesn't yet understand what happens, and is greeted with multiple permission requests. The user isn't likely to approve them.
It makes more sense to wait for the user to make the action that requires the permission and only then request it.
3. What happens if the user doesn't give your app all the permissions? You need to track this state and disable features.
It is easier to always call rp.CheckAndRequest before accessing the sensitive resource. The dialog will only be displayed once anyway.
4. Not very common, but users can disable permissions in the settings app. This means that even if the permission was granted when the app starts it can later be revoked.
 
Upvote 0

davemorris

Active Member
Licensed User
Longtime User
Hi Guys
This is very interesting discussion about how and when to use permissions - but I do believe to should be moved to its own thread, perhaps entitled something like "Guidelines on when and how to use Permissions" its going to get lost here.

My problem (fixed thanks to the suggestion from Alex_197) , unless I am wrong appears simply to ask the question?

Why does this statement hang, when used in a class module for versions of B4A v9.9+ but will work in the Activity module?
B4X:
Wait For Activity_PermissionResult(permission As String, result As Boolean)

Regards
Dave
 
Upvote 0

davemorris

Active Member
Licensed User
Longtime User
Hi, Erel
Thank you for the clarification - I missed it, and was drawn to your suggestion about B4XPages.
Regards
Dave
 
Upvote 0
Top