Discover Trigger.io Forge v2.4: Runtime App Permissions

runtime-app-permissions

Following our announcement of Trigger.io Forge Platform v2.4 earlier this month I’m pleased to present, as promised, our first article about the new features that landed with this release.

Today I’ll be covering the support we’ve added for managing iOS and Android runtime permissions and showing you:

  • How you can use our Runtime Permission features to increase your app install rates.
  • How to dynamically adapt your app to the permission preferences of your users.
  • How to save your users from an epic journey into their device preferences if they didn’t grant an app permission the first time round.

What Are Runtime Permissions?

Both iOS and Android apps execute inside a sandboxed environment which places hard restrictions on the device resources accessible by your app.

The goal of this sandboxed environment is to limit the amount of mischief a malicious or misbehaving app can inflict on your device.

In a perfectly secure world, apps would not be able to access any resource outside of their own environment. Unfortunately this would also mean we could not develop apps that make use of device features such as cameras, photo albums, geolocation or notifications.

The compromise then is for apps to explicitly request the user to grant specific “device permissions” to the app.

This informs your users of the device capabilities they are entrusting to your app, but it also places the onus on you, the app developer, to give the user a reason to trust you!

On older versions of Android, and a lesser extent iOS, the user was forced into an all-or-nothing decision about whether to grant access to resources during the initial app installation process.

Given how long the list of requested device permissions can get this unfortunately results in many users responding to such a big “ask” by simply not installing the app.

It’s a little hard to win your user’s trust if they’re not running your app in the first place, right? :-)

Luckily, with the release of Android Marshmallow, Forge v2.4 and our new forge.permissions module, users no longer have to make an upfront leap of faith as it’s now possible to incrementally request device permissions at runtime on both iOS and Android.

This helps your users feel more in control, while simultaneously giving you a chance to make a powerful case for the benefits of trusting you with their device.

Forge and Runtime Permissions

Up till now, the way we’ve dealt with runtime permission requests on iOS and Android Marshmallow has been to automatically trigger the system permission request dialog whenever a module calls a native API requiring that permission.

For example:

Which results in an app flow that looks like this:

Default Runtime Permissions Flow

The good news is that this behaviour has not changed with the release of v2.4 and if you’re satisfied with the way your app works you can stop reading right now. :-)

However, an important gotcha to be aware of is that both Android and iOS devices have the following behaviours hardcoded into their operating systems:

  • On Android: When a user clicks “No” the first time they are asked, they will have the option to prevent the app from making subsequent requests.
  • On iOS: When a user clicks “No” the first time they are asked, the app will be prevented from making subsequent requests.

What this means is that once a permission request has been denied, there is a high likelihood that the only way the user can grant that permission in future is by digging in their device’s System Preferences.

Or to put it another way, once a permission request has been denied (iOS) or disabled (Android) all future requests to forge.contact.selectAll() will only ever trigger the error callback.

Not an ideal situation, but all is not lost!

We created the forge.permissions module to address precisely this problem and to help you get more control over when and how permission requests are presented.

How To Use The forge.permissions Module

Step 0: Update your platform version and modules to the latest versions

To use the forge.permissions module you need to be on at least platform version v2.4.1 and at least the following module versions:

module version
contact 2.9
calendar 2.7
geolocation 2.4
camera 2.3
file 2.11

Step 1: Add the permissions module to your app

In the modules section of your app’s src/config.json file add the module as follows:

Alternatively, launch the Trigger.io Toolkit and navigate to the Modules section of your app and search for the permissions module.

Step 2: Check Whether You Need To Make A Permission Request

Before we actually request a permission we first need to check whether the user has already granted the permission or not.

Once we know this, we will know whether we will need to initiate a permissions request or whether we can proceed normally with our app.

The API that will give us this information is: forge.permissions.check()

So, let’s say we have a feature that needs to use the forge.contact.selectAll() API which relies on the forge.permissions.contacts.read permission.

To perform the check you then simply do something like this:

You can find a list of modules and the permissions they require by checking out the Permissions Module Documentation

When granted is true you can simply continue with your app flow and when it is false you can take the steps needed to make a permission request of the user.

Step 3: Request Permission

Now that you know how to check for a permission, you will need to know how to handle the case where the permission has not yet been granted.

To do this we’ll use the forge.permissions.request() API:

Note that, although the user will be presented with the permissions popup when you call forge.permissions.request() this is slightly deceptive.

The dialog the user will see is not generated by the device operating system but rather by the module. If the user clicks “No” in this dialog any future requests for the permission will no longer fail automatically.

It is only after the user has clicked “Yes” that the real system dialog is presented.

With this code, your user will be asked for permission when you call forge.permissions.request() and you then have the option to take an alternate action if the user did not grant the request.

All Together Now

Now that you know how to check for and request permissions, let’s look at an example of how you could put all the pieces together for a smooth user experience in your app:

Custom Runtime Permissions Flow

There are a couple of advantages to doing it this way:

  • The call to forge.permissions.check() provides a logical place to fork your app logic depending on whether the user has already granted the permission or not.
  • By linking the forge.permissions.request() call to a user action which explicitly relates to the permission being requested you greatly reduce uncertainty in the user’s mind about the purpose of the permission request.
  • Being able to check the outcome of the permission request you’re able to easily update your application and explain to the user why you need access to that permission.

That said, this is only one example of how to do it and you may find your application needs a different approach.

For some great ideas on increasing Runtime Permissions conversion I highly recommend you check out this article by Brenden Mulligan: The Right Way To Ask Users For iOS Permissions

Finally, don’t forget to check out the documentation for the Permissions module!

Conclusion

I hope you enjoyed this quick journey through the iOS & Android Runtime Permissions models, how Forge handles permissions by default and the tutorial on how to use the forge.permissions module to implement custom handling of runtime permissions.

As always, please hit us up at support@trigger.io if you have any questions or comments!