UNPKG

@nativescript/local-notifications

Version:

The Local Notifications plugin allows your app to show notifications when the app is not running.

260 lines 11.9 kB
import { Application, Color, Device, Utils } from '@nativescript/core'; import { check, request } from '@nativescript-community/perms'; import { LocalNotificationsCommon } from './common'; const NotificationManagerCompatPackageName = useAndroidX() ? global.androidx.core.app : android.support.v4.app; function useAndroidX() { return global.androidx && global.androidx.appcompat; } (() => { const registerLifecycleEvents = () => { com.telerik.localnotifications.LifecycleCallbacks.registerCallbacks(Application.android.nativeApp); }; // Hook on the application events if (Application.android.nativeApp) { registerLifecycleEvents(); } else { Application.on(Application.launchEvent, registerLifecycleEvents); } })(); export class LocalNotificationsImpl extends LocalNotificationsCommon { static getIntervalMilliseconds(interval, ticks = 1) { if (!interval) { return 0; } let multiplier = 1000; switch (interval) { default: case 'second': multiplier = 1000; break; case 'minute': multiplier = android.app.AlarmManager.INTERVAL_HOUR / 60; break; case 'hour': multiplier = android.app.AlarmManager.INTERVAL_HOUR; break; case 'day': multiplier = android.app.AlarmManager.INTERVAL_DAY; break; case 'week': multiplier = android.app.AlarmManager.INTERVAL_DAY * 7; break; // close enough case 'month': multiplier = android.app.AlarmManager.INTERVAL_DAY * 31; break; case 'quarter': multiplier = android.app.AlarmManager.INTERVAL_DAY * 31 * 3; break; case 'year': multiplier = android.app.AlarmManager.INTERVAL_DAY * 365; break; } return Math.abs(ticks) * multiplier; } static getIcon(context /* android.content.Context */, resources, iconLocation) { const packageName = context.getApplicationInfo().packageName; return (iconLocation && typeof iconLocation === 'string' && iconLocation.indexOf(Utils.RESOURCE_PREFIX) === 0 && resources.getIdentifier(iconLocation.substr(Utils.RESOURCE_PREFIX.length), 'drawable', packageName)) || (LocalNotificationsImpl.IS_GTE_LOLLIPOP && resources.getIdentifier('ic_stat_notify_silhouette', 'drawable', packageName)) || resources.getIdentifier('ic_stat_notify', 'drawable', packageName) || context.getApplicationInfo().icon; } static cancelById(id) { const context = Utils.android.getApplicationContext(); const notificationIntent = new android.content.Intent(context, com.telerik.localnotifications.NotificationAlarmReceiver.class).setAction('' + id); let flags = 0; if (parseInt(Device.sdkVersion) >= 31) { flags |= 33554432; } const pendingIntent = android.app.PendingIntent.getBroadcast(context, 0, notificationIntent, flags); const alarmManager = context.getSystemService(android.content.Context.ALARM_SERVICE); alarmManager.cancel(pendingIntent); const notificationManager = context.getSystemService(android.content.Context.NOTIFICATION_SERVICE); notificationManager.cancel(id); com.telerik.localnotifications.Store.remove(context, id); } async hasPermission() { try { return await LocalNotificationsImpl.canSend(); } catch (ex) { console.log('Error in LocalNotifications.hasPermission: ' + ex); throw ex; } } async requestPermission() { try { await LocalNotificationsImpl.ensurePreconditions(); return true; } catch (ex) { console.log('Error in LocalNotifications.requestPermission: ' + ex); return false; } } addOnMessageReceivedCallback(onReceived) { return new Promise((resolve, reject) => { try { // note that this is ONLY triggered when the user clicked the notification in the statusbar com.telerik.localnotifications.LocalNotificationsPlugin.setOnMessageReceivedCallback(new com.telerik.localnotifications.LocalNotificationsPluginListener({ success: (notification) => { onReceived(JSON.parse(notification)); }, })); resolve(); } catch (ex) { console.log('Error in LocalNotifications.addOnMessageReceivedCallback: ' + ex); reject(ex); } }); } addOnMessageClearedCallback(onReceived) { return new Promise((resolve, reject) => { try { // note that this is ONLY triggered when the user clicked the notification in the statusbar com.telerik.localnotifications.LocalNotificationsPlugin.setOnMessageClearedCallback(new com.telerik.localnotifications.LocalNotificationsPluginListener({ success: (notification) => { onReceived(JSON.parse(notification)); }, })); resolve(); } catch (ex) { console.log('Error in LocalNotifications.addOnMessageClearedCallback: ' + ex); reject(ex); } }); } cancel(id) { return new Promise((resolve, reject) => { try { LocalNotificationsImpl.cancelById(id); resolve(true); } catch (ex) { console.log('Error in LocalNotifications.cancel: ' + ex); reject(ex); } }); } cancelAll() { return new Promise((resolve, reject) => { try { const context = Utils.android.getApplicationContext(); // if (android.os.Build.VERSION.SDK_INT >= 26) { // const notificationManager = context.getSystemService(android.content.Context.NOTIFICATION_SERVICE); // console.log(">> >= 26, getActiveNotifications: " + notificationManager.getActiveNotifications()); // } else { // console.log(">> < 26, StatusBarNotification[0]: " + new android.service.notification.StatusBarNotification[0]); // } const keys = com.telerik.localnotifications.Store.getKeys(Utils.android.getApplicationContext()); for (let i = 0; i < keys.length; i++) { LocalNotificationsImpl.cancelById(parseInt(keys[i])); } NotificationManagerCompatPackageName.NotificationManagerCompat.from(context).cancelAll(); resolve(); } catch (ex) { console.log('Error in LocalNotifications.cancelAll: ' + ex); reject(ex); } }); } getScheduledIds() { return new Promise((resolve, reject) => { try { const keys = com.telerik.localnotifications.Store.getKeys(Utils.android.getApplicationContext()); const ids = []; for (let i = 0; i < keys.length; i++) { ids.push(parseInt(keys[i])); } resolve(ids); } catch (ex) { console.log('Error in LocalNotifications.getScheduledIds: ' + ex); reject(ex); } }); } async schedule(scheduleOptions) { try { await LocalNotificationsImpl.ensurePreconditions(); const context = Utils.android.getApplicationContext(); const resources = context.getResources(); const scheduledIds = []; // TODO: All these changes in the options (other than setting the ID) should rather be done in Java so that // the persisted options are exactly like the original ones. for (const s of scheduleOptions) { const entry = LocalNotificationsImpl.createScheduleEntry(s); // Some properties should not be inherited by options const nativeOptions = { ...entry, color: undefined, notificationLed: undefined }; const { interval, ticks } = LocalNotificationsImpl.getIntervalData(entry); nativeOptions.atTime = entry.at ? entry.at.getTime() : 0; nativeOptions.icon = LocalNotificationsImpl.getIcon(context, resources, (LocalNotificationsImpl.IS_GTE_LOLLIPOP && entry.silhouetteIcon) || entry.icon); nativeOptions.repeatInterval = LocalNotificationsImpl.getIntervalMilliseconds(interval, ticks); if (entry.color instanceof Color) { nativeOptions.color = entry.color.android; } if (entry.notificationLed !== true && entry.notificationLed instanceof Color) { nativeOptions.notificationLed = entry.notificationLed.android; } registerNotification(nativeOptions, context, scheduledIds); if (interval && entry.displayImmediately) { nativeOptions.id = LocalNotificationsImpl.generateNotificationID(); nativeOptions.atTime = 0; registerNotification(nativeOptions, context, scheduledIds); } } return scheduledIds; } catch (ex) { console.log('Error in LocalNotifications.schedule: ' + ex); throw ex; } function registerNotification(nativeOptions, context, register) { com.telerik.localnotifications.LocalNotificationsPlugin.scheduleNotification(new org.json.JSONObject(JSON.stringify(nativeOptions)), context); register.push(nativeOptions.id); console.log(`Notification (id ${nativeOptions.id}) scheduled successfully`); } } static async ensurePreconditions() { const hasPermission = await LocalNotificationsImpl.hasPermission(); if (!hasPermission) { const granted = await LocalNotificationsImpl.requestPermission(); if (!granted) throw new Error('Permission not granted'); } // AFAIK can't do it on this platform. when 'false' is returned, the app could prompt the user to manually enable them in the Device Settings const enabled = LocalNotificationsImpl.areEnabled(); if (!enabled) throw new Error('Notifications were manually disabled'); } static async canSend() { const hasPermission = await LocalNotificationsImpl.hasPermission(); const areEnabled = LocalNotificationsImpl.areEnabled(); return hasPermission && areEnabled; } static areEnabled() { const context = Utils.android.getApplicationContext(); return !context || NotificationManagerCompatPackageName.NotificationManagerCompat.from(context).areNotificationsEnabled(); } static async hasPermission() { const result = await check('notification'); return LocalNotificationsImpl.isAuthorized(result); } static async requestPermission() { try { const result = await request('notification'); return LocalNotificationsImpl.isAuthorized(result); } catch (ex) { return false; } } static isAuthorized(result) { const [status, _] = result; return status === 'authorized'; } } LocalNotificationsImpl.IS_GTE_LOLLIPOP = android.os.Build.VERSION.SDK_INT >= 21; export const LocalNotifications = new LocalNotificationsImpl(); //# sourceMappingURL=index.android.js.map