Italian [B4A] Problemi con i permessi e Wait For

Elric

Well-Known Member
Licensed User
Ciao a tutti!

Alcuni permessi vengono rilasciati per mezzo di "messaggio" (es. SEND_SMS), altri bisogna settarli in apposita pagina delle impostazioni (es. Overlay permission).

Nonostante io usi il Wait For, l'app li richiede in maniera asincrona e anche se alla fine riesco a dare tutti i consensi, è molto pasticciato e non mi piace. Intanto mi chiede i permessi da settare nelle impostazioni, mentre io vorrei che aspetti che io dia i permessi richiesti per messaggio. Ma poi, mentre io clicco sullo switch delle impostazioni, improvvisamente mi appare il messaggio ed è un casotto.

Più che altro non capisco perché ignora il Wait For.

B4X:
Private Sub B4XPage_Created (Root1 As B4XView) ' non è la B4XMainPage, che mi serve ad altro.
    Root = Root1
    ...
    Inizializzazioni varie, caricamento database etc.
    ...
    Wait For (ManageCheckAndRequestPermissionsByMessage) Complete (myynResult1 As Boolean)
    Wait For (ManageCheckAndRequestPermissionsBySettings) Complete (myynResult2 As Boolean)
End Sub

Private Sub B4XPage_Appear
    ...
    ...
End Sub

Private Sub B4XPage_PermissionResult (Permission As String, Result As Boolean)
   'vuota
End Sub
...
...
...
#Region GetPermission
Private Sub ManageCheckAndRequestPermissionsByMessage As ResumableSub
    Dim rp As RuntimePermissions
    For Each Permission As String In Array(rp.PERMISSION_READ_CONTACTS, rp.PERMISSION_READ_PHONE_STATE, rp.PERMISSION_POST_NOTIFICATIONS, rp.PERMISSION_SEND_SMS, rp.PERMISSION_CALL_PHONE, rp.PERMISSION_READ_CALL_LOG)
        rp.CheckAndRequest(Permission)
        LogColor($"Ask for ${Permission}"$, xui.Color_RGB(255, 165, 0))
        Wait For B4XPage_PermissionResult(Permission As String, Result As Boolean)
        LogColor($"${Permission} = ${Result}"$, xui.Color_Red)
        If Result = False Then
            ToastMessageShow($"${Permission} needed!"$, True)
            'B4XPages.ClosePage(Me) 'Non mi serve
        End If
    Next
End Sub
   
Private Sub ManageCheckAndRequestPermissionsBySettings As ResumableSub
   
    LogColor($"Ask for Overlay Permission"$, xui.Color_RGB(255, 165, 0))
    Wait For (CheckAndRequestOverlayPermission) Complete (myynGranted1 As Boolean)
    LogColor($"Overlay Permission: ${myynGranted1}"$, xui.Color_Red)
    If myynGranted1 = False Then
        ToastMessageShow("Accesso Non Disturbare mancante", True)
        Return myynGranted1
    End If
   
    LogColor($"Ask for DoNotDisturbPermission"$, xui.Color_RGB(255, 165, 0))
    Wait For (CheckAndRequestDoNotDisturbPermission) Complete (myynGranted2 As Boolean)
    LogColor($"DoNotDisturbPermission: " ${myynGranted2}"$, xui.Color_Red)
    If myynGranted2 = False Then
        ToastMessageShow("Accesso Non Disturbare mancante", True)
        Return myynGranted2
    End If
   
    LogColor($"Ask for ManageWriteSettingsPermission"$, xui.Color_RGB(255, 165, 0))
    Wait For (CheckAndRequestManageWriteSettingsPermission) Complete (myynGranted3 As Boolean)
    LogColor($"ManageWriteSettingsPermission: ${myynGranted2}"$, xui.Color_Red)
    If myynGranted3 = False Then
        ToastMessageShow("Accesso Write Settings mancante", True)
        Return myynGranted3
    End If
   
    LogColor($"Ask for IgnoreBatteryOptimization"$, xui.Color_RGB(255, 165, 0))
    Wait For (CheckAndRequestIgnoreBatteryOptimization) Complete (myynIgnoring As Boolean)
    LogColor($"IgnoreBatteryOptimization: " ${myynIgnoring}"$, xui.Color_Red)
    If myynIgnoring = False Then
        ToastMessageShow($"IgnoreBatteryOptimization = ${myynIgnoring}"$, True)
        Return myynGranted3
    End If
   
    Return myynGranted1
End Sub

Private Sub CheckAndRequestReadContacts As ResumableSub
    Dim rp As RuntimePermissions
    Dim mystrPermission As String = rp.PERMISSION_READ_CONTACTS
    rp.CheckAndRequest(mystrPermission)
   
    Wait For B4XPage_PermissionResult(Permission As String, Result As Boolean)
    Log($"${mystrPermission} = ${Result}"$)
    If Result = False Then
        ToastMessageShow($"No ${mystrPermission}!"$, True)
'        B4XPages.ClosePage(Me) 'Non mi serve
    End If
    Return Result
End Sub

Private Sub CheckAndRequestReadPhoneState As ResumableSub
    Dim rp As RuntimePermissions
    Dim mystrPermission As String = rp.PERMISSION_READ_PHONE_STATE
    rp.CheckAndRequest(mystrPermission)
   
    Wait For B4XPage_PermissionResult(Permission As String, Result As Boolean)
    Log($"${mystrPermission} = ${Result}"$)
    If Result = False Then
        ToastMessageShow($"No ${mystrPermission}!"$, True)
'        B4XPages.ClosePage(Me) 'Non mi serve
    End If
    Return Result
End Sub

Private Sub CheckAndRequestPostNotification As ResumableSub
    Dim rp As RuntimePermissions
    Dim mystrPermission As String = rp.PERMISSION_POST_NOTIFICATIONS
    rp.CheckAndRequest(mystrPermission)
   
    Wait For B4XPage_PermissionResult(Permission As String, Result As Boolean)
    Log($"${mystrPermission} = ${Result}"$)
    If Result = False Then
        ToastMessageShow($"No ${mystrPermission}!"$, True)
'        B4XPages.ClosePage(Me) 'Non mi serve
    End If
    Return Result
End Sub

Private Sub CheckAndRequestCallPhoneLog As ResumableSub
    Dim rp As RuntimePermissions
    Dim mystrPermission As String = rp.PERMISSION_CALL_PHONE
    rp.CheckAndRequest(mystrPermission)
   
    Wait For B4XPage_PermissionResult(Permission As String, Result As Boolean)
    Log($"${mystrPermission} = ${Result}"$)
    If Result = False Then
        ToastMessageShow($"No ${mystrPermission}!"$, True)
'        B4XPages.ClosePage(Me) 'Non mi serve
    End If
    Return Result
End Sub

Private Sub CheckAndRequestReadCallLog As ResumableSub
    Dim rp As RuntimePermissions
    Dim mystrPermission As String = rp.PERMISSION_READ_CALL_LOG
    rp.CheckAndRequest(mystrPermission)
   
    Wait For B4XPage_PermissionResult(Permission As String, Result As Boolean)
    Log($"${mystrPermission} = ${Result}"$)
    If Result = False Then
        ToastMessageShow($"No ${mystrPermission}!"$, True)
'        B4XPages.ClosePage(Me) 'Non mi serve
    End If
    Return Result
End Sub

Private Sub CheckAndRequestSendSMS As ResumableSub
    Dim rp As RuntimePermissions
    Dim mystrPermission As String = rp.PERMISSION_SEND_SMS
    rp.CheckAndRequest(mystrPermission)
   
    Wait For B4XPage_PermissionResult(Permission As String, Result As Boolean)
    Log($"${mystrPermission} = ${Result}"$)
    If Result = False Then
        ToastMessageShow($"No ${mystrPermission}!"$, True)
'        B4XPages.ClosePage(Me) 'Non mi serve
    End If
    Return Result
End Sub

'Manifest: AddPermission(android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
Private Sub CheckAndRequestIgnoreBatteryOptimization As ResumableSub
    Dim myPhone As Phone
    If myPhone.SdkVersion < 23 Then
        Return True
    End If
    Dim context As JavaObject
    context.InitializeContext
    Dim PowerManager As JavaObject = context.RunMethod("getSystemService", Array("power"))
    Dim ignoring As Boolean = PowerManager.RunMethod("isIgnoringBatteryOptimizations", Array(Application.PackageName))
    If ignoring Then
        Return True
    End If
    Dim myIntent As Intent
    myIntent.Initialize("android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS", "package:" & Application.PackageName)
    StartActivity(myIntent)
    Wait For B4XPage_Appear 'Change to Activity_Resume if mistakenly not using B4XPages.
    Return PowerManager.RunMethod("isIgnoringBatteryOptimizations", Array(Application.PackageName))
End Sub

#Region CheckAndRequest Overlay Permission
'Spostamento su altre app
Public Sub CheckAndRequestOverlayPermission As ResumableSub
    Dim myPhone As Phone
    If myPhone.SdkVersion >= 23 Then
        Dim settings As JavaObject
        settings.InitializeStatic("android.provider.Settings")
        Dim ctxt As JavaObject
        ctxt.InitializeContext
        If settings.RunMethod("canDrawOverlays", Array(ctxt)) = True Then
            Return True
        End If
        Dim myIntent As Intent
        myIntent.Initialize("android.settings.action.MANAGE_OVERLAY_PERMISSION", "package:" & Application.PackageName)
        StartActivityForResult(myIntent)
        Wait For ion_Event (MethodName As String, Args() As Object)
        Return settings.RunMethod("canDrawOverlays", Array(ctxt))
    Else
        Return True
    End If
End Sub

' ResumableSub per Do Not Disturb (API23+)
Public Sub CheckAndRequestDoNotDisturbPermission As ResumableSub
    Dim myPhone As Phone
    If myPhone.SdkVersion < 23 Then Return True

    Dim jo As JavaObject
    jo.InitializeContext
    Dim nm As JavaObject = jo.RunMethod("getSystemService", Array("notification"))
    Dim accessGranted As Boolean = nm.RunMethod("isNotificationPolicyAccessGranted", Null)
    If accessGranted Then Return True

    Dim i As Intent
    i.Initialize("android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS", "")
    i.Flags = 0x10000000 ' FLAG_ACTIVITY_NEW_TASK
    StartActivity(i)

    Wait For B4XPage_Appear 'Wait For Activity_Resume
    ' Re-check
    nm = jo.RunMethod("getSystemService", Array("notification"))
    If nm.RunMethod("isNotificationPolicyAccessGranted", Null) Then
        Return True
    Else
        Return False
    End If
End Sub

Private Sub StartActivityForResult(i As Intent)
    Dim jo As JavaObject = GetBA
    ion = jo.CreateEvent("anywheresoftware.b4a.IOnActivityResult", "ion", Null)
    jo.RunMethod("startActivityForResult", Array As Object(ion, i))
End Sub

Private Sub GetBA As Object
    Dim jo As JavaObject = Me
    Return jo.RunMethod("getBA", Null)
End Sub
#End Region

#Region Manage Write Settings
Private Sub CheckAndRequestManageWriteSettingsPermission As ResumableSub
    If CanWriteToSystemSettings = False Then
        Dim myIntent As Intent
        myIntent.Initialize("android.settings.action.MANAGE_WRITE_SETTINGS", "package:" & Application.PackageName)
        StartActivity(myIntent)
        Wait For B4XPage_Appear 'Wait For Activity_Resume
        If CanWriteToSystemSettings = False Then
            Log("no permission...")
            Return False
        Else
            Return True
        End If
    Else
        Return True
    End If
End Sub

Sub CanWriteToSystemSettings As Boolean
    Dim myphone As Phone
    If myphone.SdkVersion >= 23 Then
        Dim ctxt As JavaObject
        ctxt.InitializeContext
        Dim settings As JavaObject
        settings.InitializeStatic("android.provider.Settings.System")
        Return settings.RunMethod("canWrite", Array(ctxt))
    End If
    Return True
End Sub
#End Region
#End Region
 

Sagenut

Expert
Licensed User
Longtime User
Anche se forse non è il problema, farei in modo che la sub Created si concluda prima di iniziare a richiedere i permessi.
Quindi qualcosa così
B4X:
Private Sub B4XPage_Created (Root1 As B4XView) ' non è la B4XMainPage, che mi serve ad altro.
    Root = Root1
    ...
    Inizializzazioni varie, caricamento database etc.
    ...
    RichiestaPermessi
End Sub

Private Sub RichiestaPermessi
Wait For (ManageCheckAndRequestPermissionsByMessage) Complete (myynResult1 As Boolean)
    Wait For (ManageCheckAndRequestPermissionsBySettings) Complete (myynResult2 As Boolean)
End Sub
 
Upvote 0

udg

Expert
Licensed User
Longtime User
Nella PermissionbyMessage non hai un Return pur essendo una resumable.
Seguirei comunque il consiglio di Sagenut che rende tutto più pulito e leggibile. Oltre all'aspetto Create già citato
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Anche se forse non è il problema, farei in modo che la sub Created si concluda prima di iniziare a richiedere i permessi.
Quindi qualcosa così
B4X:
Private Sub B4XPage_Created (Root1 As B4XView) ' non è la B4XMainPage, che mi serve ad altro.
    Root = Root1
    ...
    Inizializzazioni varie, caricamento database etc.
    ...
    RichiestaPermessi
End Sub

Private Sub RichiestaPermessi
Wait For (ManageCheckAndRequestPermissionsByMessage) Complete (myynResult1 As Boolean)
    Wait For (ManageCheckAndRequestPermissionsBySettings) Complete (myynResult2 As Boolean)
End Sub
In quel modo non sarebbe molto diverso, perché la Sub RichiestaPermessi è anch'essa una Resumable, dato che contiene delle Wait For.
Per attendere che la Create venga completata, dovresti chiamarla con:
B4X:
CallSubDelayed(Me, "RichiestaPermessi")

Altro metodo può essere spostare le due Wait For nella B4XPage_Appear. E' vero che in questo modo il controllo avverrebbe ogni volta che la pagina venisse mostrata, ma si tratta codice eseguito molto velocemente, solo un controllo su poche variabili boolean locali (i permessi).
 
Last edited:
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
1766223901621.png


Quella va eliminata, attendi l'evento PermissionResult in un altro punto del tuo sorgente:

1766224009696.png
 
Upvote 0

Elric

Well-Known Member
Licensed User
Grazie a tutti. Influenza permettendo, faccio le modifiche e vi aggiorno.

Al solito, dopo prove e prove ho postato un codice già sbagliato visto che ManageCheckAndRequestPermissionsBySettings ha 5 Return di cui solo uno servirebbe (anche se poi i permessi me li chiede tutti) e ManageCheckAndRequestPermissionsByMessage non ha neanche un Return. 🥲

Farlo alle 2 di notte non aiuta...
 
Upvote 0
Top