Asking for Permission

Phones and browsers guard the camera, photos, location, calendar and microphone. Your app asks for one at the moment it needs it, with a sentence you write saying why, and you decide what happens when the answer is no. One design asks the right way on iOS, Android and the web.

Ask for permission

Add Ask for permission to a button (or anywhere an action runs) and pick what it asks for: Camera, Photos, Location, Calendar or Microphone. It is most useful on a screen that explains first, “We use your location to show events near you”, with a button that then asks. People say yes more often when they know why.

Already allowedOn granted runs straight away. Nobody is asked twice.
Not asked yetThe system asks, in its own dialog, showing your message. Yes runs On granted; no runs On denied.
Refused for goodOn denied runs without asking: the system will not show its dialog again. (After a refusal that can still be asked again, as Android allows once, the dialog shows again.)

Both outcomes are optional. Like any action, more steps can follow it, and it can sit in either arm of a branch.

When the answer is no

Inside On denied, the data picker offers the denial's reason, so the app can say the right thing or branch on it:

deniedRefused this time. Asking again later can still show the dialog.
blockedRefused for good: the system will not ask again. Only the person can change it, in Settings. Pair this with Open app settings.
unavailableThe device or browser has no such thing: no camera, or a browser without location.

The reason exists only inside On denied; Checks flags it anywhere else. With no On denied at all, the app is not left silent: it says the permission is off, and on a phone the message carries an Open settings button. On the web it says how to allow it in the browser's site settings instead.

Open app settings

Open app settings takes the person to your app's page in the phone's Settings, where they can switch a permission back on. Use it in On denied when the reason is blocked, since asking again will not work.

On the web

A browser cannot open its own settings for a page, so on the web this action shows how to allow the permission in the browser instead. Checks notes this on a web app that uses it.

Photos and the calendar

Some actions ask by themselves, so they need no Ask for permission in front of them:

Take a photoFrom the camera, the camera is asked for first. Refused, On denied runs and the camera never opens; without one, the app says it is off, with Open settings on a phone. Recording a video also needs the microphone message.
From the libraryNothing is asked: the system photo picker needs no permission, so there is no On denied. iOS still needs the Photos message.
Add to calendarAsked for only on iOS 16 and earlier. Refused, On denied runs; On error stays for a real failure, such as an event with no start.

The reason reads the same inside each of these On denied steps: denied, blocked or unavailable.

Taking a photo on the web

A browser owns its camera. On a phone, Take a photo opens the phone's camera; on a computer, a file chooser. Nothing is asked, so On denied never runs on the web, and Checks notes it.

Permission messages

iOS shows your sentence in its dialog, and Apple rejects apps whose sentence is missing or vague. In the App panel, Permission messages has one field for each permission your app uses (asked for with Ask for permission, or needed by Take a photo, a library pick or Add to calendar), and nothing is filled in for you. Say what the app does with it:

good messages
text
Camera     Gather uses the camera to scan tickets at check-in.
Location   Gather uses your location to show events near you.

Checks warns about every permission the app uses that has no message. It is a warning, not a blocker: the export still runs, but the iOS build will be rejected until it is filled in.

What each export writes

Flutter. The app asks through permission_handler. Koolbase never writes the ios/ or android/ folders, so the entries are ready to merge, in koolbase/permissions/, each saying where it goes. Merge them once; a re-export never touches your files. .koolbase/export.json lists them under required_platform_config, as “asking for permissions”.

koolbase/permissions/
text
Info.plist.xml        your messages → ios/Runner/Info.plist
Podfile.txt           the permission_handler switches for what the app asks → ios/Podfile
AndroidManifest.xml   the <uses-permission> entries → android/app/src/main/AndroidManifest.xml

Expo. Each feature asks through its own Expo module, and your messages are written into app.json on every export.

Web. The browser asks when the camera, microphone or location is first used. Choosing a photo and adding to a calendar need no browser permission, so they count as allowed.

Photos on Android

Android's own photo picker needs no permission, so Photos counts as allowed there and the app never asks. Google Play rejects apps that ask for full photo access without a strong reason.

Checking on a device

The system's dialog appears only on a real device or simulator. To see it again after answering, reset the app's permissions:

terminal
Bash
# iOS simulator: forget every answer for the app
xcrun simctl privacy booted reset all com.gather.attendee

# Android: take one permission back
adb shell pm revoke com.gather.attendee android.permission.CAMERA

To try the blocked case, refuse in the dialog, then switch the permission off in Settings. The next ask goes straight to On denied with the reason blocked.