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.
2 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.
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.
3.1 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.
Keep in mind that the permission names are different for each platform. For example, if you need to request permission to access reading contacts you will need to call the actions twice: one for iOS permission (CONTACTS_IOS) and one for Android permission (READ_CONTACTS_ANDROID).
3.2 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.
When the permission is blocked, if a user requests it a pop-up window will ask them to open their settings to grant the permission. Furthermore, the Mendix developer will receive a blocked status.
These permissions statuses match the statuses that are received from the action, so you should not override them.
3.3 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}:
4 Building
4.1 Development
4.1.1 IOS
The following permissions can be tested using the iOS Make It Native app:
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.
The permissions that you cannot find using the Native Builder UI can be added manually per the Update Native App Permissions section below.
5 Updating Native App Permissions
5.1 iOS
Update your ios/podfile file with the needed permissions:
target 'YourAwesomeProject' do
# …
permissions_path = '../node_modules/react-native-permissions/ios'
pod 'Permission-AppTrackingTransparency', :path => "#{permissions_path}/AppTrackingTransparency"
pod 'Permission-BluetoothPeripheral', :path => "#{permissions_path}/BluetoothPeripheral"
pod 'Permission-Calendars', :path => "#{permissions_path}/Calendars"
pod 'Permission-Camera', :path => "#{permissions_path}/Camera"
pod 'Permission-Contacts', :path => "#{permissions_path}/Contacts"
pod 'Permission-FaceID', :path => "#{permissions_path}/FaceID"
pod 'Permission-LocationAccuracy', :path => "#{permissions_path}/LocationAccuracy"
pod 'Permission-LocationAlways', :path => "#{permissions_path}/LocationAlways"
pod 'Permission-LocationWhenInUse', :path => "#{permissions_path}/LocationWhenInUse"
pod 'Permission-MediaLibrary', :path => "#{permissions_path}/MediaLibrary"
pod 'Permission-Microphone', :path => "#{permissions_path}/Microphone"
pod 'Permission-Motion', :path => "#{permissions_path}/Motion"
pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications"
pod 'Permission-PhotoLibrary', :path => "#{permissions_path}/PhotoLibrary"
pod 'Permission-PhotoLibraryAddOnly', :path => "#{permissions_path}/PhotoLibraryAddOnly"
pod 'Permission-Reminders', :path => "#{permissions_path}/Reminders"
pod 'Permission-Siri', :path => "#{permissions_path}/Siri"
pod 'Permission-SpeechRecognition', :path => "#{permissions_path}/SpeechRecognition"
pod 'Permission-StoreKit', :path => "#{permissions_path}/StoreKit"
end
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:
<manifestxmlns:android="http://schemas.android.com/apk/res/android"package="com.myawesomeapp"><!-- Keep only the permissions used in your app --><uses-permissionandroid:name="android.permission.ACCEPT_HANDOVER"/><uses-permissionandroid:name="android.permission.ACCESS_BACKGROUND_LOCATION"/><uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION"/><uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/><uses-permissionandroid:name="android.permission.ACCESS_MEDIA_LOCATION"/><uses-permissionandroid:name="android.permission.ACTIVITY_RECOGNITION"/><uses-permissionandroid:name="com.android.voicemail.permission.ADD_VOICEMAIL"/><uses-permissionandroid:name="android.permission.ANSWER_PHONE_CALLS"/><uses-permissionandroid:name="android.permission.BLUETOOTH_ADVERTISE"/><uses-permissionandroid:name="android.permission.BLUETOOTH_CONNECT"/><uses-permissionandroid:name="android.permission.BLUETOOTH_SCAN"/><uses-permissionandroid:name="android.permission.BODY_SENSORS"/><uses-permissionandroid:name="android.permission.BODY_SENSORS_BACKGROUND"/><uses-permissionandroid:name="android.permission.CALL_PHONE"/><uses-permissionandroid:name="android.permission.CAMERA"/><uses-permissionandroid:name="android.permission.GET_ACCOUNTS"/><uses-permissionandroid:name="android.permission.NEARBY_WIFI_DEVICES"/><uses-permissionandroid:name="android.permission.POST_NOTIFICATIONS"/><uses-permissionandroid:name="android.permission.PROCESS_OUTGOING_CALLS"/><uses-permissionandroid:name="android.permission.READ_CALENDAR"/><uses-permissionandroid:name="android.permission.READ_CALL_LOG"/><uses-permissionandroid:name="android.permission.READ_CONTACTS"/><uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permissionandroid:name="android.permission.READ_MEDIA_AUDIO"/><uses-permissionandroid:name="android.permission.READ_MEDIA_IMAGES"/><uses-permissionandroid:name="android.permission.READ_MEDIA_VIDEO"/><uses-permissionandroid:name="android.permission.READ_PHONE_NUMBERS"/><uses-permissionandroid:name="android.permission.READ_PHONE_STATE"/><uses-permissionandroid:name="android.permission.READ_SMS"/><uses-permissionandroid:name="android.permission.RECEIVE_MMS"/><uses-permissionandroid:name="android.permission.RECEIVE_SMS"/><uses-permissionandroid:name="android.permission.RECEIVE_WAP_PUSH"/><uses-permissionandroid:name="android.permission.RECORD_AUDIO"/><uses-permissionandroid:name="android.permission.SEND_SMS"/><uses-permissionandroid:name="android.permission.USE_SIP"/><uses-permissionandroid:name="android.permission.UWB_RANGING"/><uses-permissionandroid:name="android.permission.WRITE_CALENDAR"/><uses-permissionandroid:name="android.permission.WRITE_CALL_LOG"/><uses-permissionandroid:name="android.permission.WRITE_CONTACTS"/><uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/><!-- … --></manifest>