Page tree
Skip to end of metadata
Go to start of metadata

This guide explains how application permissions can be managed in Smartface.

Why permissions are required ?

Users must grant permission for an app to access sensitive information, including the current location, calendar, contact information, reminders, and photos. Although people appreciate the convenience of using an app that has access to this information, they also expect to have control over their privacy.
Permission managements should be developed OS specific in the applications. 

How it Works ?

iOS

Smartface iOS Frameworks handles permissions automatically for the user. Developer does not need to handle permission management. For example, lets open GPS sensor of the device shown as below;

function Application_OnStart(e) {
	include("pages/index.js");
	Pages.page1.show();
	Device.setGPSStatus(1);
}

Here is the screenshot when the code is executed;

Android

Android 4.0+ - 6.0 Versions

Before marshmallow version, permissions are defined in AndroidManifest.xml. User can grant all permission while installing the application. In android M still user need to request the permission from manifest. Since android M addition to manifest permissions, from code sensitive permission checks must be done

Android Manifest file can be reachable under the path config/Android in the workspace.

Here is a screenshot of permission page while installing the application;

Android 6.0+

When Android Marshmallow is released, permission system of Android is totally changed. Permissions are given while using the application like iOS systems.

In the javaScript side, there are some methods which are neccessary for managing permissions for Android 6.0+ devices.

Table in the below shows the functioanlity and their required permissions;

Application.checkPermission Function

This function checks if one of the dangerous permissions is granted at beginning or not. For android versions earlier than 6.0, it will return value exists in manifest or not. For permissions in same category with one of the permissions is approved earlier, checking will return as it is not required to request for the same category permission.

Permission name can be a value for name of the permission.
The example below assuming READ_CALENDAR is; 

Application.checkPermission(Application.Permissions.CALENDAR); //returns true or false
Application.checkPermission("READ_CALENDAR"); //returns true or false
Application.checkPermission("WRITE_CALENDAR"); //returns false, because it is not in manifest
Application.checkPermission("The quick brown fox jumps over the lazy dog"); //returns false, because it is not a permission
Application.checkPermission("android.permission.READ_CALENDAR"); //returns true or false
Application.checkPermission("permission.READ_CALENDAR"); //returns false, because it is not a permission that matches to the pattern
Application.checkPermission("read calendar"); //All letters are converted to upper case and spaces are replaced with _; so same as READ_CALENDAR; returns true or false
Application.checkPermission("android.permission.read calendar"); //returns false, because it is not a permission that matches to the pattern
Application.checkPermission(); //returns false
Application.requestPermissions Function

With Application.requestPermissions function, Android System Dialog will appear to ask for permission grant by user for dangerous(privacy) permissions. This function accepts array of strings similar to checkPermission function. In the background this function checks for permissions then fires Application.onRequestPermissionsResult event.

Later when Application.onRequestPermissionsResult event is called, values are matching in same order as given array in permissionNames parameter.

var lastRequestPermissionCode = 1000; 
Application.requestPermissions(lastRequestPermissionCode++, [Application.Permissions.READ_CALENDAR, Application.Permissions.SENSORS]); //will display 2 confirmation dialog
Application.requestPermissions(lastRequestPermissionCode++, Application.Permissions.READ_CALENDAR); //will display 1 confirmation dialog
Application.requestPermissions(lastRequestPermissionCode++, [Application.Permissions.READ_CALENDAR, "GET_ACCOUNTS"]); //will display 2 confirmation dialog
Application.requestPermissions(lastRequestPermissionCode++, Application.Permissions.READ_CALENDAR, "GET_ACCOUNTS"); //will display 2 confirmation dialog
Application.requestPermissions(Application.Permissions.READ_CALENDAR, "GET_ACCOUNTS"); //throws error for first argument is NaN (not a number)

Displayed confirmation dialog strings, localisations and customisations cannot be made by framework, it is managed by OS.

Application.onRequestPermissionsResult Event

This event is called after Application.requestPermissions function. This event is fired  asynchronous way, there is no way to make sure which request is answered.

var lastRequestPermissionCode = 1000;
Application.onRequestPermissionsResult = function (e) {
    if(rc !== e.requestCode) return;
    var calenderApproved = e.results[0]; // result for Application.Permissions.READ_CALENDAR; true or false
    var sensorsApproved = e.results[1]; // undefined; 1 length array
    alert(JSON.stringify(e.requestedPermissions)); //will alert ["READ_CALENDAR"]
};
var rc = lastRequestPermissionCode++;
Application.requestPermissions(rc, Application.Permissions.READ_CALENDAR);

There will be only one onRequestPermissionsResult event in whole application. So for multiple requests, it should be handled per requestCode.

Application.onRequestPermissionsResult = function (e) {
    switch(e.requestCode) {
        case 1001:
            var camera = e.results[0];
            var storage = e.results[1];
            //[write your logic of btn1.onPressed continuation]
        break;
        case 1002:
            var calendar = e.results[0];
            //[write your logic of btn2.onPressed continuation]
        break;
    }
};
  
  
btn1.onPressed = function() {
    Application.requestPermissions(1001, ["CAMERA", "WRITE_EXTERNAL_STORAGE"])
};
  
btn2.onPressed = function() {
    Application.requestPermissions(1002, "READ_CALENDAR");
};

Or it is possible to write a generic handler for all permissions as below;

Application.onRequestPermissionsResult = function (e) {
    var cameraIndex = e.requestedPermissions.indexOf("CAMERA");
    if(cameraIndex > -1) {
        var cameraPermission = e.results[cameraIndex];
        //[write your own logic for camera]
    }
    var sendSMSIndex = e.requestedPermissions.indexOf("SEND_SMS");
    if(sendSMSIndex > -1) {
        var sendSMSPermission = e.results[sendSMSIndex];
        //[write your own logic for sending sms]
    }
    // and so on ...
};
 
btn1.onPressed = function() {
    Application.requestPermissions(1001, ["CAMERA", "WRITE_EXTERNAL_STORAGE"])
};
  
btn2.onPressed = function() {
    Application.requestPermissions(1002, "SEND_SMS");
};
Application.shouldShowRequestPermissionRationale Function

This method checks for a permission is shown before to user and the program is about to request the same permission again.

	 var lastRequestCode = 1000;

	 function page1_btn_onPressed(e) {
	 	var rc = lastRequestCode++;
	 	Application.onRequestPermissionsResult = function(e) {
	 		if (e.requestCode !== rc) return;
	 		if (e.results[0]) {
	 			requestCamera();
	 		}
	 	};

	 	function requestCamera() {
	 		var permission = Application.Permissions.CAMERA;
	 		if (Application.shouldShowRequestPermissionRationale(permission))
	 			alert({
	 				message: "Application requires camera permission to proceed",
	 				title: "Camera Permission",
	 				firstButtonText: "Retry",
	 				onFirstButtonPressed: function(e) {
	 					Application.requestPermissions(permission);
	 				}
	 			});
	 		else {
	 			Application.requestPermissions(rc, permission);
	 		}
	 	}
	 	requestCamera();
	 }

permissions.js library

permissions.js is a library which is written by Smartface to make permission management easier.

Since Android 6.0 (Marshmallow) some intensive permissions are asked to user regardles they are being stated in manifest file. Smartface has implemented same usage of Native Android Permission management. However in terms of JavaScript using the same structure is not that effective. With using this library:

  • checkPermission function checks & requests permissions if required with a callback. It is possible to state a rationale (reason) why those permissions are required
  • applyPermission function is same as Function.prototype.apply with checkPermission functionality

How to Use ?

List of Permission Functions;

  • SMF.Net.sendSMS
  • SMF.Multimedia.startCamera
  • SMF.Multimedia.pickFromGallery
  • SMF.Multimedia.getGalleryItems
  • SMF.Multimedia.saveToGallery
  • Device.Contacts.addContact
  • Device.Contacts.pick
  • Device.Contacts.getAll
  • Device.setGPSStatus
  • Application.onSMSReceived
  • SMF.Multimedia.startCamera
  • Device.Contacts.addContact
  • Device.Contacts.getAll
  • Device.share
  • Device.setGPSStatus
  • Device.Contacts.pick


Smf-js-libs is a asynchronous library. It's using error first pattern. 

You need to download smf-js-libs repository and place these files into scripts folder of your workspace. After that, include permissions.js into app.js file shown as below;

After including , you can use predefined global methods to grant access of permissions. Here is an example of location permission for GPS as below;

function Application_OnStart(e) {
	include("pages/index.js");
	Pages.page1.show();
	
	global.setGPSStatus({
    setGPSStatus: true,
    done: function(err) {
     if(err) return alert(err);
    }
});
}

After the app is started permission dialog will shown to user as below;