requestAppPermission for PhotoLibrary

Dear Corona-community,

I can successfully ask for permission for using the camera on my Honor 8, running Android 7:

local hasAccessToCamera, hasCamera = media.hasSource(media.Camera) if (hasAccessToCamera == true) then --take picture media.capturePhoto( { listener=cameraListener } ) elseif(hasCamera == true and native.canShowPopup("requestAppPermission")) then -- A camera exists, but there is no access to it! native.showPopup( "requestAppPermission", { appPermission="Camera" } ) else [...]

Problem is that if I try to add an image from the photolibrary BEFORE getting this permission, media.selectPhoto does not work. So, I guess media.selectPhoto also requires this permission.

According to

https://docs.coronalabs.com/api/library/media/hasSource.html

only media.hasSource( media.Camera ) returns two booleans. But it looks like there is nothing similar for media.hasSource(media.PhotoLibrary).

I tried to ask for the same permission when trying to add an image from library:

local hasAccessToGallery, hasGallery = media.hasSource(media.Camera) if (hasAccessToGalery == true) then -- get picture from gallery media.selectPhoto( { mediaSource = media.photoLibrary, listener = cameraListener } ) elseif(hasGallery == true and native.canShowPopup("requestAppPermission")) then -- gallery exists, but there is no access to it! native.showPopup( "requestAppPermission", { appPermission="Camera" } ) else [...]

which results in asking for permission when I click on my gallery-button. Problem is, even if I accept permission, next time I click on the button corona crashes again, giving me a nil for event.target in my listener.

Any ideas?

Before I forget: My build.settings contain this:

android =
    {
        usesPermissions =
        {
            “android.permission.INTERNET”,
            “android.permission.CAMERA”,
            “android.permission.WRITE_EXTERNAL_STORAGE”
        },
    },

New observation:

My Honor 8 running Android 7 requires two appPermissions to successfully use media.selectPhoto : STORAGE and CAMERA. As long as I have not requested these two permissions, event.target in my listener is nil.

So, what’s the best way to ask for both permissions, and, once given, do media.selectPhoto with just one click? Right now I have:

-- function to add picture from gallery function addImageFromGallery() local hasAccessToGalery, hasGallery = media.hasSource(media.Camera) if (hasAccessToGalery == true) then -- get picture from gallery media.selectPhoto( {listener = cameraListener } ) elseif(hasGallery == true and native.canShowPopup("requestAppPermission")) then -- gallery exists, but there is no access to it! native.showPopup( "requestAppPermission", { appPermission="STORAGE" } ) native.showPopup( "requestAppPermission", { appPermission="CAMERA" } ) else -- load default image faverPicture = display.newImage("default1.jpg") end end 

It looks totally wrong to me. User has to click three times on the button: First time, access to “library, media and files” is requested, second time, “access to camera” is requested and finally, third click, library opens.

How can I do this with just one tap?

Thank you

Figured it out: When I click on my “add gallery-image” button, the following listener is called, where

native.showPopup( “requestAppPermission”, { appPermission={“STORAGE”, “CAMERA”}, listener = permissionListener} )

asks for both permissions with just one tap.

-- function to add picture from gallery function addImageFromGallery() -- special case: Android \>= 6.0, where permission has to be granted if ( system.getInfo( "platform" ) == "android" and system.getInfo( "androidApiLevel" ) \>= 23 ) then -- if both permissions are granted, add image from gallery local permsGranted = checkPermissions() if(permsGranted) then media.selectPhoto( {listener = cameraListener } ) -- if permissions are not yet granted, ask for them else native.showPopup( "requestAppPermission", { appPermission={"STORAGE", "CAMERA"}, listener = permissionListener} ) end -- all other devices: iOS, android \< 6.0 else -- check if we have access to library if (media.hasSource( media.photoLibrary )) then -- get picture from gallery media.selectPhoto( {listener = cameraListener } ) -- if not, show hint and use default picture else composer.showOverlay( "hint", {isModal = true, effect = "fade", time = 200, params={hint = "Leider keine Galerie vorhanden."}} ) -- load default image faverPicture = display.newImage("default1.jpg") end end end 

checkPermissions looks like this:

-- checks CAMERA and STORAGE permissions (required for Android \> 6) function checkPermissions() -- get all permissions in table local grantedPermissions = system.getInfo("grantedAppPermissions") -- loop through them and check for CAMERA and STORAGE permissions for i = 1, #grantedPermissions do if("Storage" == grantedPermissions[i]) then storageGranted = true elseif("Camera" == grantedPermissions[i]) then cameraGranted = true end end -- return true if both permissions are granted if(storageGranted and cameraGranted) then return true else return false end end

and my permissionListener, called once user has granted or declined permissions, looks like this:

-- listener called when asking for permission function permissionListener(event) local permsGranted = checkPermissions() -- if permissions are now granted, open library if(permsGranted) then media.selectPhoto( {listener = cameraListener } ) -- if permissions are still not granted, show warning else composer.showOverlay( "hint", {isModal = true, effect = "fade", time = 200, params={hint = "Ohne Zugriff auf deine Galerie kannst du leider keine Faver erstellen."}} ) end end

It works. When user taps on gallery button after a fresh installation, both CAMERA and STORAGE permissions pop up. In case he accepts both, library is opened. If not, an Overlay prints a warning.

I’d still appreciate if someone could varify this solution :slight_smile:

Thanks

Before I forget: My build.settings contain this:

android =
    {
        usesPermissions =
        {
            “android.permission.INTERNET”,
            “android.permission.CAMERA”,
            “android.permission.WRITE_EXTERNAL_STORAGE”
        },
    },

New observation:

My Honor 8 running Android 7 requires two appPermissions to successfully use media.selectPhoto : STORAGE and CAMERA. As long as I have not requested these two permissions, event.target in my listener is nil.

So, what’s the best way to ask for both permissions, and, once given, do media.selectPhoto with just one click? Right now I have:

-- function to add picture from gallery function addImageFromGallery() local hasAccessToGalery, hasGallery = media.hasSource(media.Camera) if (hasAccessToGalery == true) then -- get picture from gallery media.selectPhoto( {listener = cameraListener } ) elseif(hasGallery == true and native.canShowPopup("requestAppPermission")) then -- gallery exists, but there is no access to it! native.showPopup( "requestAppPermission", { appPermission="STORAGE" } ) native.showPopup( "requestAppPermission", { appPermission="CAMERA" } ) else -- load default image faverPicture = display.newImage("default1.jpg") end end 

It looks totally wrong to me. User has to click three times on the button: First time, access to “library, media and files” is requested, second time, “access to camera” is requested and finally, third click, library opens.

How can I do this with just one tap?

Thank you

Figured it out: When I click on my “add gallery-image” button, the following listener is called, where

native.showPopup( “requestAppPermission”, { appPermission={“STORAGE”, “CAMERA”}, listener = permissionListener} )

asks for both permissions with just one tap.

-- function to add picture from gallery function addImageFromGallery() -- special case: Android \>= 6.0, where permission has to be granted if ( system.getInfo( "platform" ) == "android" and system.getInfo( "androidApiLevel" ) \>= 23 ) then -- if both permissions are granted, add image from gallery local permsGranted = checkPermissions() if(permsGranted) then media.selectPhoto( {listener = cameraListener } ) -- if permissions are not yet granted, ask for them else native.showPopup( "requestAppPermission", { appPermission={"STORAGE", "CAMERA"}, listener = permissionListener} ) end -- all other devices: iOS, android \< 6.0 else -- check if we have access to library if (media.hasSource( media.photoLibrary )) then -- get picture from gallery media.selectPhoto( {listener = cameraListener } ) -- if not, show hint and use default picture else composer.showOverlay( "hint", {isModal = true, effect = "fade", time = 200, params={hint = "Leider keine Galerie vorhanden."}} ) -- load default image faverPicture = display.newImage("default1.jpg") end end end 

checkPermissions looks like this:

-- checks CAMERA and STORAGE permissions (required for Android \> 6) function checkPermissions() -- get all permissions in table local grantedPermissions = system.getInfo("grantedAppPermissions") -- loop through them and check for CAMERA and STORAGE permissions for i = 1, #grantedPermissions do if("Storage" == grantedPermissions[i]) then storageGranted = true elseif("Camera" == grantedPermissions[i]) then cameraGranted = true end end -- return true if both permissions are granted if(storageGranted and cameraGranted) then return true else return false end end

and my permissionListener, called once user has granted or declined permissions, looks like this:

-- listener called when asking for permission function permissionListener(event) local permsGranted = checkPermissions() -- if permissions are now granted, open library if(permsGranted) then media.selectPhoto( {listener = cameraListener } ) -- if permissions are still not granted, show warning else composer.showOverlay( "hint", {isModal = true, effect = "fade", time = 200, params={hint = "Ohne Zugriff auf deine Galerie kannst du leider keine Faver erstellen."}} ) end end

It works. When user taps on gallery button after a fresh installation, both CAMERA and STORAGE permissions pop up. In case he accepts both, library is opened. If not, an Overlay prints a warning.

I’d still appreciate if someone could varify this solution :slight_smile:

Thanks