You install a hiking app, tap "show me on the map", and a box pops up: Allow "TrailPal" to use your location? Why does the app have to ask at all? It's running on your phone. This page explains the idea behind it, the sandbox, what the different answers really mean on iPhone and Android, and what a developer has to do so their app asks politely and keeps working when you say no.

Every app lives in its own box

On a phone, each app runs inside a sandbox: a walled-off area that the operating system (iOS or Android, the software that runs the phone itself) sets up when the app is installed. Inside its box an app can do what it likes with its own files: its settings, the trails you saved, its cached images. Outside the box it can't simply look around.

That rules out two kinds of access. First, other apps' boxes. Your hiking app can't read your banking app's data or your chat history, full stop. There's no permission for that, so there's nothing to ask. Second, shared, sensitive things the phone owns: your location, the camera, the microphone, your photos, your contacts. Those sit behind a gate the operating system guards. An app can reach them only if you've said yes. That "yes" is a permission.

Flip the switches below to give TrailPal permissions and watch which wires go live. Tap the other apps too.

The sandbox · what can TrailPal reach?

OTHER APPS THIS APP PHONE'S STUFF sandbox wall OS gate Bank appbalance, logins Chat appyour messages TrailPalits own filessaved trailssettings, cachealways OK

Notice what isn't on the right: the internet. On both iOS and Android, an ordinary app can go online without asking you anything. Android does have an INTERNET permission, but it's a "normal" one that's granted automatically at install. The prompts are saved for things that are personal or that could be used to spy on you.

Why bother with all this? Because you install apps from strangers. The sandbox means a buggy or sneaky app can't quietly read everything on the phone. The worst it can do is mess up its own box, plus whatever you explicitly let it touch.

The prompt: asked at the moment it's needed

Older Android versions showed a list of permissions before you installed an app, take it or leave it. Since Android 6.0 (2015), the sensitive ones are runtime permissions: the app asks while it's running, usually the first time you use a feature that needs it. iPhones have worked that way for years. The box that pops up is drawn by the operating system, not by the app, so an app can't fake the buttons or pre-tick "Allow".

The answers you can give are more than yes or no:

Location has one more choice: precise or approximate. Precise means where you're actually standing. Approximate means a rough area; Android's documentation puts it at about 3 square kilometres. A weather app only needs your town, so approximate is plenty. Turn-by-turn directions need precise.

Now try it. Tap a feature in the sample app, answer the prompts, and see how a well-built app reacts to each answer. Switch between iPhone and Android, and use the controls under the phone to leave the app or open the phone's Settings.

Permission simulator · TrailPal

9:41
TrailPal

What happened

The developer's job here

A few things worth spotting in the simulator. On iOS, "Don't Allow" is final as far as the app is concerned: iOS shows the system prompt only once per permission, and every later request just gets the stored "no". The only way back is the Settings app. Android is a little more forgiving: after a first "Don't allow" the app may ask again, ideally after explaining why. But on Android 11 and later, if you deny the same permission twice, Android stops showing the dialog and the app's request is refused automatically.

Also look at the top of the phone while the camera or microphone is on. iOS shows a green dot for the camera and an orange dot for the microphone. Android 12 and later shows a green indicator for either. Those are drawn by the system, so the app can't hide them.

What the developer has to do

As a developer, you don't get to skip the prompt, and you can't word the buttons. What you do control is three things: declaring what you might need, choosing when to ask, and handling every possible answer.

1. Declare it up front

On iOS, every sensitive permission needs a usage description in the app's Info.plist file (a settings file bundled with every iPhone app). It's a sentence, written by you, that iOS shows inside the prompt. Forget it, and iOS refuses: for the camera or microphone it actually shuts the app down on the spot when it tries to use them.

<key>NSCameraUsageDescription</key>
<string>Take photos of the trail and attach them to your hike.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Show where you are on the trail map.</string>

On Android, you list permissions in AndroidManifest.xml (the file that describes the app to the system). If a permission isn't listed there, a request for it is denied without any dialog.

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Here's how the common ones line up:

WhatiOS: Info.plist keyAndroid: manifest permission
CameraNSCameraUsageDescriptionCAMERA
MicrophoneNSMicrophoneUsageDescriptionRECORD_AUDIO
Location while usingNSLocationWhenInUseUsageDescriptionACCESS_COARSE_LOCATION (approximate), ACCESS_FINE_LOCATION (precise)
Location alwaysNSLocationAlwaysAndWhenInUseUsageDescriptionACCESS_BACKGROUND_LOCATION

Declaring is not the same as getting. It only says "this app may ask". The user still decides at runtime.

2. Ask at the right moment, with a reason

An app that fires five prompts the second it opens gets five "Don't allow"s. Ask when the user taps the feature, so the reason is obvious. Many apps show their own short screen first ("TrailPal uses your location to put you on the map") and only then trigger the system prompt. That's what the simulator does. On Android, the system even tells you when the user has refused once, through a function called shouldShowRequestPermissionRationale(): that's your cue to explain before asking again.

3. Check, then handle every answer

Before using the camera, an app checks the current status, and there are three cases: allowed (go ahead), not asked yet (ask), refused (fall back). Here's the Android version in Kotlin, the main language for Android apps:

private val askCamera = registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
    if (granted) openCamera() else offerTextNoteInstead()
}

fun onPhotoTapped() {
    when {
        ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) ==
            PackageManager.PERMISSION_GRANTED -> openCamera()
        shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) ->
            explainThenAsk()   // they said no once: explain first
        else -> askCamera.launch(Manifest.permission.CAMERA)
    }
}

And the same idea on iOS in Swift:

switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
    openCamera()
case .notDetermined:
    AVCaptureDevice.requestAccess(for: .video) { granted in
        DispatchQueue.main.async {
            if granted { openCamera() } else { offerTextNoteInstead() }
        }
    }
default:   // .denied or .restricted: no prompt will appear
    showOpenSettingsButton()
}

Functions like openCamera() and offerTextNoteInstead() are the app's own; the rest are the platforms' real APIs (APIs are the ready-made functions the system gives you). The important part is the shape: "no" is a normal answer, not a crash. A good app keeps working with less: type a trail name instead of using GPS, write a text note instead of a voice note. And when the user can only fix things in Settings, it offers a button that jumps straight there. Both systems allow that link: iOS through UIApplication.openSettingsURLString, Android through the Settings.ACTION_APPLICATION_DETAILS_SETTINGS screen.

One more rule: permissions can change behind your back. The user can switch them off in Settings at any time, "Allow Once" and "Only this time" expire, and Android can automatically remove permissions from apps you haven't used for a few months. So an app checks the status every time it needs access, not just once at startup.

Check yourself

TrailPal wants to read the messages stored by your chat app. Which permission does it need to ask for?

Each app's private data lives in its own sandbox. There's no permission that opens another app's box, so there's nothing the user could even say yes to.

On an iPhone you tapped "Don't Allow" for the camera. The app calls the camera request again. What happens?

iOS shows each system prompt only once. After that, the stored answer comes back straight away. The user can change it only in Settings, which is why good apps offer an "Open Settings" button.

A weather app only needs to know which town you're in. What should it ask for?

Ask for the least you need. A town-level forecast works fine with approximate location, and it only needs it while you're looking at the app. Less access means more people say yes.

An Android developer forgets to add CAMERA to AndroidManifest.xml but still requests it in code. What does the user see?

Android only lets an app ask for permissions it declared. An undeclared one is refused automatically, so the feature silently fails, a classic bug when you're starting out.

The short version

Next time a prompt pops up, you'll know what you're really deciding: which door in the sandbox to open, for how long, and how wide.

The prompts in the simulator are simplified mock-ups; exact wording and layout change between iOS and Android versions.