Android 6.0 storage permission not working

There have been some vague posts about permissions on android 6.0 but there were no real answers. Also corona documentation that does mention permissions doesn’t really go into much detail for android 6.0.

Basically or situation is that after updating one of our devices to android 6.0, when we install our app, the storage permission does not get automatically switched on, even though we ask for the permission in the build.settings.

Only by going into the device settings > application > manually switching storage permission on will the app function properly.

Can corona provide more specific documentation on how to correctly use permissions in android 6.0?

In our case vungle ads don’t work when the storage permission is off.

Vungle suggested…

<uses-permission android:name=“android.permission.WRITE_EXTERNAL_STORAGE” android:maxSdkVersion=“18” />

…but i have not seen any way to set the maxSDKVersion for individual permissions in corona. Note: Once storage permission is manually switched on vungle ads works fine.

Hi jacques1,

The runtime permissions scheme on Android works differently than what you may have seen on iOS. On iOS, the operating system will initiate asking for permissions when the user requests access to something potentially privacy-invading, such as the Camera. Native iOS developers can also request permissions manually if they choose.

On Android, permissions must be requested programmatically by the app developer. Around February 2016, we added some new options to existing Corona APIs to allow for requesting permissions, checking what permissions an app already has, etc. See our Introducing new Android 6 Features for more info.

One subtlety that we could document better is that you  need to have the permissions you want to request in build.settings.

In your case of requesting storage permission:

  • Add the “android.permission.WRITE_EXTERNAL_STORAGE” permission to your build.settings:

    settings = { – … android = { usesPermissions = { “android.permission.WRITE_EXTERNAL_STORAGE”, – … }, }, – … }

You are correct that Corona does not provide a way to set the maxSdkVersion for a <uses-permission> tag, but in your case, you don’t need it.

  • In you Lua code, you can then request storage permission using either:

    local options = { appPermission = “Storage” } native.showPopup( “requestAppPermission”, options )

  • or the Android-specific way:

    local options = { appPermission = “android.permission.WRITE_EXTERNAL_STORAGE” } native.showPopup( “requestAppPermission”, options )

The requestapppermission option of native.showPopup() details the options you have for requesting permissions programmatically.

See our Camera sample for an illustration of all the features added for Android 6 at work.

Hi Caleb thank you,

adding user required permissions in build.settings has been well explained in the documentation that’s no problem as I’ve always used that way for all our android apps. But android 6.0 took me off guard with it not automatically asking/granting the permissions even though they were set in the build.settings.

Requiring additional permission request code in the main.lua is something that perhaps needs to be added/explained in more detail in the corona documentation.

I did finally find some code which I am using, I’d just like to confirm if I need to use all the code below or can I simply use the few lines of code you mentioned. Lastly, do I need to check for the android OS version or is it okay to run this code regardless of the OS version?

local function appPermissionsListener( event )

    for k,v in pairs( event.grantedAppPermissions ) do

         if ( v == “Storage” ) then

             print( “** Storage permission granted! **” )

         end

   end

end

local options =

{

    appPermission = “Storage”,

    urgency = “Critical”,

    listener = appPermissionsListener,

    rationaleTitle = “Storage access required”,

    rationaleDescription = “Storage access is required for storing player data. Re-request now?”,

    settingsRedirectTitle = “Alert”,

    settingsRedirectDescription = “Without the ability to store data, this app cannot properly function. Please grant storage access within Settings.”

}

native.showPopup( “requestAppPermission”, options )

Hi jacques1,

Our documentation on permissions could definitely be improved as there’s useful fragments in different places, but tying everything together from those pieces isn’t the most obvious thing.

The absolute minimum you need to request permissions on Android would be the few lines I mentioned earlier. But it’s probably in your best interest to also provide a listener to the options table so that you can allow your app to do whatever action requires a dangerous permission as soon as that permission is granted.

Instead of checking the OS version, you should check to make sure that you can show the requestAppPermission popup. This will future-proof your code more should the permissions framework be added to other platforms.

All that being said, the code to request Storage permission only on platforms where you need to would look something like:

local function isStoragePermissionGranted( grantedAppPermissionsTable ) for k,v in pairs( grantedAppPermissionsTable ) do if ( v == "Storage" ) then print( "\*\* Storage permission granted! \*\*" ) return true end end return false end local function appPermissionsListener( event ) if ( isStoragePermissionGranted( event.grantedAppPermissions ) ) then -- Do stuff requiring storage permission else -- Handle not having storage permission end end if ( not isStoragePermissionGranted( system.getInfo( "grantedAppPermissions" ) ) then if ( native.canShowPopup( "requestAppPermission" ) ) then -- Request Storage Permission. local options = { appPermission = "Storage", listener = appPermissionsListener, } native.showPopup( "requestAppPermission", options ) else -- You need to add a permission in the Storage group to your build.settings. end end&nbsp;

Hope that helps.

Cheers for the help Ajay.

Hi jacques1,

The runtime permissions scheme on Android works differently than what you may have seen on iOS. On iOS, the operating system will initiate asking for permissions when the user requests access to something potentially privacy-invading, such as the Camera. Native iOS developers can also request permissions manually if they choose.

On Android, permissions must be requested programmatically by the app developer. Around February 2016, we added some new options to existing Corona APIs to allow for requesting permissions, checking what permissions an app already has, etc. See our Introducing new Android 6 Features for more info.

One subtlety that we could document better is that you  need to have the permissions you want to request in build.settings.

In your case of requesting storage permission:

  • Add the “android.permission.WRITE_EXTERNAL_STORAGE” permission to your build.settings:

    settings = { – … android = { usesPermissions = { “android.permission.WRITE_EXTERNAL_STORAGE”, – … }, }, – … }

You are correct that Corona does not provide a way to set the maxSdkVersion for a <uses-permission> tag, but in your case, you don’t need it.

  • In you Lua code, you can then request storage permission using either:

    local options = { appPermission = “Storage” } native.showPopup( “requestAppPermission”, options )

  • or the Android-specific way:

    local options = { appPermission = “android.permission.WRITE_EXTERNAL_STORAGE” } native.showPopup( “requestAppPermission”, options )

The requestapppermission option of native.showPopup() details the options you have for requesting permissions programmatically.

See our Camera sample for an illustration of all the features added for Android 6 at work.

Hi Caleb thank you,

adding user required permissions in build.settings has been well explained in the documentation that’s no problem as I’ve always used that way for all our android apps. But android 6.0 took me off guard with it not automatically asking/granting the permissions even though they were set in the build.settings.

Requiring additional permission request code in the main.lua is something that perhaps needs to be added/explained in more detail in the corona documentation.

I did finally find some code which I am using, I’d just like to confirm if I need to use all the code below or can I simply use the few lines of code you mentioned. Lastly, do I need to check for the android OS version or is it okay to run this code regardless of the OS version?

local function appPermissionsListener( event )

    for k,v in pairs( event.grantedAppPermissions ) do

         if ( v == “Storage” ) then

             print( “** Storage permission granted! **” )

         end

   end

end

local options =

{

    appPermission = “Storage”,

    urgency = “Critical”,

    listener = appPermissionsListener,

    rationaleTitle = “Storage access required”,

    rationaleDescription = “Storage access is required for storing player data. Re-request now?”,

    settingsRedirectTitle = “Alert”,

    settingsRedirectDescription = “Without the ability to store data, this app cannot properly function. Please grant storage access within Settings.”

}

native.showPopup( “requestAppPermission”, options )

Hi jacques1,

Our documentation on permissions could definitely be improved as there’s useful fragments in different places, but tying everything together from those pieces isn’t the most obvious thing.

The absolute minimum you need to request permissions on Android would be the few lines I mentioned earlier. But it’s probably in your best interest to also provide a listener to the options table so that you can allow your app to do whatever action requires a dangerous permission as soon as that permission is granted.

Instead of checking the OS version, you should check to make sure that you can show the requestAppPermission popup. This will future-proof your code more should the permissions framework be added to other platforms.

All that being said, the code to request Storage permission only on platforms where you need to would look something like:

local function isStoragePermissionGranted( grantedAppPermissionsTable ) for k,v in pairs( grantedAppPermissionsTable ) do if ( v == "Storage" ) then print( "\*\* Storage permission granted! \*\*" ) return true end end return false end local function appPermissionsListener( event ) if ( isStoragePermissionGranted( event.grantedAppPermissions ) ) then -- Do stuff requiring storage permission else -- Handle not having storage permission end end if ( not isStoragePermissionGranted( system.getInfo( "grantedAppPermissions" ) ) then if ( native.canShowPopup( "requestAppPermission" ) ) then -- Request Storage Permission. local options = { appPermission = "Storage", listener = appPermissionsListener, } native.showPopup( "requestAppPermission", options ) else -- You need to add a permission in the Storage group to your build.settings. end end&nbsp;

Hope that helps.

Cheers for the help Ajay.