App Permissions
Introduction
Advanced features in mobile apps often require permission from users. Apps need to respect the user’s privacy, so it is common practice for an app to request the user’s permission before storing media and data. To get permission, you can build a generic JavaScript action. This generic action will allow your app to ask for specific permissions before accessing a mobile capability, such as the device camera or location.
Prerequisites
- Complete the Prerequisites section of Build a Mendix Native App in the Cloud.
- Install Mendix Studio Pro to use the Native Mobile App Builder and the latest Nanoflow Commons module.
- Confirm your Native Mobile Resources module is up to date.
- Confirm you are using the latest version of the Make It Native 10 app.
Using a Generic Permission Action
A generic permission action can be used inside nanoflows in an existing app or in a new app. With a nanoflow open, you can find it in the Toolbox under the Native Mobile section.
Naming the Permission
When using the generic permission action you must choose the permission name you need. It should be one of the available permissions in NanoflowCommons.Enum_Permissions
enumeration.
CONTACTS_IOS
) and one for Android permission (READ_CONTACTS_ANDROID
).
Action Return Type Statuses
This action returns the status of the permission after the action, and it is of type NanoflowCommons.Enum_PermissionStatus
. The statuses are as follows:
Permission status | Notes |
---|---|
NanoflowCommons.Enum_PermissionStatus.granted |
The permission is granted after requesting it from the user, or it was already granted previously. |
NanoflowCommons.Enum_PermissionStatus.unavailable |
This feature is not available on this device. |
NanoflowCommons.Enum_PermissionStatus.denied |
The permission is denied but can still be requested. |
NanoflowCommons.Enum_PermissionStatus.blocked |
The permission is blocked. The user must open the app settings themselves and grant permission from there. |
NanoflowCommons.Enum_PermissionStatus.limited |
The permission is granted but with limitations. |
Permission Usage Example
This an example for requesting contact access permission for Android and iOS devices:
- Determine the user’s running platform (Android or iOS) by using the Get device info action (in the Toolbox’s Native mobile section).
- Branch your logic based on the current platform:
-
For the Android branch, use a Generic permission action with a permission name like {READ_CONTACTS_ANDROID}.
-
For the iOS branch, use a Generic permission action with a permission name like {CONTACTS_IOS}:
-
Building
Development
iOS
The following permissions can be tested using the iOS Make It Native app:
- CAMERA
- FACE_ID
- LOCATION_WHEN_IN_USE
- MICROPHONE
- PHOTO_LIBRARY
To test the remaining permissions you can build native app and update the native app with the required permissions.
Android
The following permissions can be tested using the Android Make It Native app:
- ACCESS_FINE_LOCATION
- BLUETOOTH_CONNECT
- BLUETOOTH_SCAN
- CALL_PHONE
- RECORD_AUDIO
- CAMERA
- READ_EXTERNAL_STORAGE
- WRITE_EXTERNAL_STORAGE
- SCHEDULE_EXACT_ALARM
To test the remaining permissions you can build a native app and update the native app with the required permissions.
Deployment
During deployment you must specify the permissions that your application has used to be able to request them from the user on production. To do that you can navigate to App permissions while using Native Builder UI and add the permissions you are using in your application for iOS and Android.
Updating Native App Permissions
iOS
Update your ios/podfile file with the required permissions:
# ⬇️ uncomment the permissions you need
setup_permissions([
# 'AppTrackingTransparency',
# 'Bluetooth',
# 'Calendars',
# 'CalendarsWriteOnly',
# 'Camera',
# 'Contacts',
# 'FaceID',
# 'LocationAccuracy',
# 'LocationAlways',
# 'LocationWhenInUse',
# 'MediaLibrary',
# 'Microphone',
# 'Motion',
# 'Notifications',
# 'PhotoLibrary',
# 'PhotoLibraryAddOnly',
# 'Reminders',
# 'Siri',
# 'SpeechRecognition',
# 'StoreKit',
])
To allow a Siri permission you will need to enable Siri capability in your app. This can be done one of two ways:
-
The first way is by navigating to Xcode > Signing & Capabilities > + > Siri and then enabling the capability
-
The second way is by updating the /ios/{app name}/{app name}.entitlements file as follows:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <!-- … --> <key>com.apple.developer.siri</key> <true/> </dict> </plist>
Run Pod Install in your iOS directory
Run pod install
in your iOS app’s directory to install and update the necessary dependencies, including the permission-related configurations you just added.
Add Permissions Usage Descriptions
Add the corresponding permissions usage descriptions to your Info.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- 🚨 Keep only the permissions specified in setup_permissions 🚨 -->
<key>NSAppleMusicUsageDescription</key>
<string>[REASON]</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>[REASON]</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>[REASON]</string>
<key>NSCalendarsFullAccessUsageDescription</key>
<string>[REASON]</string>
<key>NSCalendarsWriteOnlyAccessUsageDescription</key>
<string>[REASON]</string>
<key>NSCameraUsageDescription</key>
<string>[REASON]</string>
<key>NSContactsUsageDescription</key>
<string>[REASON]</string>
<key>NSFaceIDUsageDescription</key>
<string>[REASON]</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>[REASON]</string>
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>YOUR-PURPOSE-KEY</key>
<string>[REASON]</string>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>[REASON]</string>
<key>NSMicrophoneUsageDescription</key>
<string>[REASON]</string>
<key>NSMotionUsageDescription</key>
<string>[REASON]</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>[REASON]</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>[REASON]</string>
<key>NSRemindersFullAccessUsageDescription</key>
<string>[REASON]</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>[REASON]</string>
<key>NSSiriUsageDescription</key>
<string>[REASON]</string>
<key>NSUserTrackingUsageDescription</key>
<string>[REASON]</string>
</dict>
</plist>
Android
Update the android/app/src/main/AndroidManifest.xml file with the permissions requried by your app’s use case. Make sure to keep only the permissions that are actually used in your app:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.myawesomeapp">
<!-- Keep only the permissions used in your app -->
<uses-permission android:name="android.permission.ACCEPT_HANDOVER" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BODY_SENSORS" />
<uses-permission android:name="android.permission.BODY_SENSORS_BACKGROUND" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.UWB_RANGING" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<!-- … -->
</manifest>