Android Question RunTime Permissions and Android 8 (with sdk 26)

Marcos Alves

Well-Known Member
Licensed User
Longtime User
Hello,

I'm having some errors trying to get permissions at runtime. The sequence is:

- The user starts the app
- The first routine is:

B4X:
Sub Activity_Resume

    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissonResult (Permission As String,Result As Boolean)
    If Result = False Then AllPermissions = False
  
    rp.CheckAndRequest(rp.PERMISSION_WRITE_CONTACTS)
    Wait For Activity_PermissonResult (Permission As String,Result As Boolean)
    If Result = False Then AllPermissions = False
  
    rp.CheckAndRequest(rp.PERMISSION_READ_CONTACTS)
    Wait For Activity_PermissonResult (Permission As String,Result As Boolean)
    If Result = False Then AllPermissions = False
  
    If AllPermissions Then
        PermissionsOk
    Else
        Msgbox("Some required permissions weren't granted.","Restart the app")
    End If

  
End Sub

When the app starts, I have the sequence:
- The first permission window opens but over this there is a system message error indicating that "The System UI has stopped".
- If you grant the rp.PERMISSION_WRITE_EXTERNAL_STORAGE (allow to message box), then app close . Reopening, the app screen is blank. Debugging the code I can notice that the app is waiting for Activity_PermissonResult in the first event, what means that the rp.PERMISSION_WRITE_EXTERNAL_STORAGE was granted but the event wasn't raised...
The screens sequence follows:
upload_2018-6-6_13-26-17.png

Is there anything wrong with the code? Is it a problem with Android 8 and SDk 26?
 

kisoft

Well-Known Member
Licensed User
Longtime User
HI
Add obtaining permission for example yes. Show errors in the debug mode.

B4X:
Sub Activity_Create(FirstTime As Boolean)
       
        Activity.LoadLayout("1")
     
        Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_RECEIVE_SMS)
        Wait For Activity_PermissionResult (Permission As String, PResult As Boolean)
        If PResult = False Then
                MsgboxAsync("no permission  RECIVE SMS", "")
                Return
        Else
                Log("permission OK RECIVE SMS")
        End If
     
        Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_SEND_SMS)
        Wait For Activity_PermissionResult (Permission As String, PResult As Boolean)
        If PResult = False Then
                MsgboxAsync("no permission SEND SMS", "")
                Return
        Else
                Log("permission OK SEND SMS ")
        End If

https://www.b4x.com/android/forum/threads/runtime-permissions-android-6-0-permissions.67689/
 
Last edited:
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
HI
Add obtaining permission for example yes. Show errors in the debug mode.

B4X:
Sub Activity_Create(FirstTime As Boolean)
      
        Activity.LoadLayout("1")
    
        Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_RECEIVE_SMS)
        Wait For Activity_PermissionResult (Permission As String, PResult As Boolean)
        If PResult = False Then
                MsgboxAsync("no permission  RECIVE SMS", "")
                Return
        Else
                Log("permission OK RECIVE SMS")
        End If
    
        Starter.rp.CheckAndRequest(Starter.rp.PERMISSION_SEND_SMS)
        Wait For Activity_PermissionResult (Permission As String, PResult As Boolean)
        If PResult = False Then
                MsgboxAsync("no permission SEND SMS", "")
                Return
        Else
                Log("permission OK SEND SMS ")
        End If

https://www.b4x.com/android/forum/threads/runtime-permissions-android-6-0-permissions.67689/
I tested on a physical device and the code runs without any error. I don't have a device with Android 8 to test (tested on Android 7). I'll proceed with some additional tests and post the results here.

Thanks!
 
Upvote 0

asales

Expert
Licensed User
Longtime User
You need to get this permissions immediately when the app is started?

I have an app that uses the EXTERNAL_STORAGE and CONTACTS permissions, but I start the runtime permissions only when the user need to read a contact or save a file.

To me this approach is better, because the user knows why the app needs the permission.

By now, if you request a permission to read a contact, the permission to write is not show, because they are in the same group, but it could be change in future versions of Android:
https://developer.android.com/guide/topics/permissions/overview#permission-groups
 
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
You need to get this permissions immediately when the app is started?

I have an app that uses the EXTERNAL_STORAGE and CONTACTS permissions, but I start the runtime permissions only when the user need to read a contact or save a file.

To me this approach is better, because the user knows why the app needs the permission.

By now, if you request a permission to read a contact, the permission to write is not show, because they are in the same group, but it could be change in future versions of Android:
https://developer.android.com/guide/topics/permissions/overview#permission-groups
Yes, I need this permission starting the app because at this time I write some files and directories those will be used by the app imediatly.
 
Upvote 0

Johan Schoeman

Expert
Licensed User
Longtime User
For what it might be worth - I guess you have seen this posting be Erel

READ_EXTERNAL_STORAGE / WRITE_EXTERNAL_STORAGE

This is the most common dangerous permission. It is added automatically when you use File.DirDefaultExternal or File.DirRootExternal.
However there is a simple workaround for this.

1. Use RuntimePermissions.GetSafeDirDefaultExternal("") instead of File.DirDefaultExternal. The parameter passed is an optional subfolder that will be created under the default folder.

2. Add this code to the manifest editor:
Code:
AddManifestText(
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
)
The explanation for this is that GetSafeDirDefaultExternal doesn't require any permission on Android 4.4+ (API 18) and requires the WRITE_EXTERNAL_STORAGE on older versions. The code above adds the permission to older devices.

You only need to deal with WRITE_EXTERNAL_STORAGE at runtime if you need access to a folder other than the app's default external folder.
 
Last edited:
Upvote 0

Yayou49

Active Member
Licensed User
I've had the same error yesterday ....
I solved this problem by showing first the container of my photo before to ask for the permission.
Not a scientific explaination, but now it works ;)
 
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
The System UI error looks like an emulator bug. You should test it on a real device.
You're right! I don't have now a physical device with Android 8 but tested on Android 7 and it's working. I'll get a physical Android 8 to confirm. Thanks @Erel
 
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
I've had the same error yesterday ....
I solved this problem by showing first the container of my photo before to ask for the permission.
Not a scientific explaination, but now it works ;)
Hi,
this could be a very interesting workaround to test on emulator... could you be more specific? You mean that if the app shows a container with an image the error in emulator doesn't occurs?
 
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
For what it might be worth - I guess you have seen this posting be Errel

READ_EXTERNAL_STORAGE / WRITE_EXTERNAL_STORAGE

This is the most common dangerous permission. It is added automatically when you use File.DirDefaultExternal or File.DirRootExternal.
However there is a simple workaround for this.

1. Use RuntimePermissions.GetSafeDirDefaultExternal("") instead of File.DirDefaultExternal. The parameter passed is an optional subfolder that will be created under the default folder.

2. Add this code to the manifest editor:
Code:
AddManifestText(
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
)
The explanation for this is that GetSafeDirDefaultExternal doesn't require any permission on Android 4.4+ (API 18) and requires the WRITE_EXTERNAL_STORAGE on older versions. The code above adds the permission to older devices.

You only need to deal with WRITE_EXTERNAL_STORAGE at runtime if you need access to a folder other than the app's default external folder.
Hello @Johan Schoeman ... I'll do a brief explanation why I'm using external storage:

- My app receives medias from remote users and these medias must to be showed on gallery
- If I use app external dir of app I will have two problems:
1. The images will not be added to gallery, besides could be accessed directly from the user BUT
2. The path is complex for a standard user... imagine: path is: //sdcard/com.myapp.extension/data/directory/ - !!!! the user will not easily access like //sdcard/whatsapp/media for example.

And more... I don't want to target SDK 18 because we know that after November/18 Google will only accept updates for apps targeted to SDK 26 or more... then it's interesting to use it now to see the possible issues and changes that app could require.
 
Upvote 0

Yayou49

Active Member
Licensed User
Hi,
this could be a very interesting workaround to test on emulator... could you be more specific? You mean that if the app shows a container with an image the error in emulator doesn't occurs?

To be clear, I have an app with barcode scanner (using phone camera).
Previously, I did load this control only after permission request and it failed as you shown.
I've change the script to ask permission only after loaded the barcode scanner control and it was successful.
 
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
To be clear, I have an app with barcode scanner (using phone camera).
Previously, I did load this control only after permission request and it failed as you shown.
I've change the script to ask permission only after loaded the barcode scanner control and it was successful.
It looks that emulator requires some object on the screen in order to work before a requestpermission... ok, thanks!
 
Upvote 0
Top