I’m creating an Ionic v5.x application using Angular v10.x with Capacitor v2.4.5, and I’m confused by Capacitor Permissions (specifically the Permissions plugin, and the associated requestPermission() methods for other plugins like Geolocation and LocalNotifications).
When the application opens it will request permissions which is expected, but when I test while the application is in use that they weren’t denied (or services were turned off) the use of requestPermissions for example const result = await LocalNotifications.requestPermissions(); always returns an empty object literal regardless of whether permissions were granted or denied. I know I can use const enabled = await LocalNotifications.areEnabled(); to check the permission state, but I thought that await LocalNotifications.requestPermissions() would show a native prompt. Is that not the case?
// Works as expected
public async hasNotificationPermissions()
const permission = await Permissions.query({ name: PermissionType.Notifications });
this.presentAlert('Permission Query', `${JSON.stringify(permission)}`); // Testing only
}
// Doesn't work as expected
public async requestPermissionsPlugin(): Promise<PermissionsRequestResult | null> {
try {
// Always an empty object literal ({})
const result = await LocalNotifications.requestPermissions();
// Expected to handle result or possibly directed into catch, but
// instead always results an empty object literal everytime, which
// I tried with LocalNotifications, Geolocation, and Permissions
this.presentAlert('Permissions Request', JSON.stringify(result)); // Testing only
return result;
} catch (e) {
this.presentAlert('Permissions Request Exception', JSON.stringify(e)); // Testing only
}
return null;
}
I’ve tested this in emulation and on my Android device, and either way invoking requestPermissions doesn’t appear to do anything. How is requestPermissions() supposed to be used? I wish the documentation for Capacitor was a bit more verbose and had a few more examples.
Thanks @rapropos. So would you say that I should be trying to use requestPermissions in code so when it is available it will just start working? For example, would you do something like this example for a bit of future proofing?
public async scheduleRenewalNotification(renewalDate: string): Promise<PermissionsRequestResult | null> {
const { value: notificationsEnabled } = await LocalNotifications.areEnabled();
if (!notificationsEnabled) {
const { granted } = await LocalNotifications.requestPermission();
if (!granted) {
return;
}
}
const expiryDate = moment(renewalDate, 'YYYY-MM-DDTkk:mm:ssZZ').local();
LocalNotifications.schedule({
notifications: [
this.addRenewalNotification(1, 'Your membership will expire in 2 weeks', expiryDate.clone().subtract(2, 'weeks')),
this.addRenewalNotification(2, 'Your membership is about to expire', expiryDate.clone().subtract(1, 'day'))
]
});
}
I don’t feel confident enough reading tea leaves here, but Capacitor 3 is in alpha now, so if you’re interested in taking a peek at the future, you could look into what it does here.
Apps should control permissions. To make great native apps, developers need full control over the permission flow. In Capacitor 2, limited control over permissions was offered in the now defunct Permissions plugin. In Capacitor 3, a framework for permissions has been implemented that gives control over permissions offered by official and third-party plugins.
I wish this was outlined in the Capacitor docs. I’ve read through the docs, read articles, and watched a lot of tutorials, and I would say based on my reading and watching that this is not well known/understood since it looks like a lot of people are using requestPermissions as if that does something.
As an alternative I pulled in the Cordova AndroidPermissions plugin, but what permission is required for local notifications? I can turn on/off notifications on my device, but trying ACCESS_NOTIFICATION_POLICY doesn’t appear to be the right permission to request permission using a native dialog.