cordova-notify-plugin 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # cordova-notify-plugin
2
+
3
+ A Cordova plugin to schedule and cancel local alarm notifications on Android.
4
+ Alarms fire even when the app is closed and survive device reboots.
5
+
6
+ ## Supported Platforms
7
+
8
+ - Android (API 19+)
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ cordova plugin add cordova-notify-plugin
14
+ ```
15
+
16
+ Or from a local path:
17
+
18
+ ```bash
19
+ cordova plugin add ../cordova-plugin-alarm-notify
20
+ ```
21
+
22
+ ## Permissions
23
+
24
+ The plugin automatically adds the following permissions to `AndroidManifest.xml`:
25
+
26
+ | Permission | Purpose |
27
+ |---|---|
28
+ | `POST_NOTIFICATIONS` | Show notification when alarm fires (Android 13+) |
29
+ | `SCHEDULE_EXACT_ALARM` | Schedule exact-time alarms (Android 12+) |
30
+ | `RECEIVE_BOOT_COMPLETED` | Re-schedule alarms after device reboot |
31
+ | `REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` | Prevent Doze mode from blocking alarms |
32
+
33
+ ## Usage
34
+
35
+ ### Schedule an Alarm
36
+
37
+ **Modern API (Promise):**
38
+
39
+ ```javascript
40
+ cordova.plugins.alarmNotify.schedule({
41
+ id: 1,
42
+ title: 'Meeting',
43
+ text: 'Team standup starts now',
44
+ at: new Date('2026-04-17T09:00:00')
45
+ })
46
+ .then(msg => console.log('Scheduled:', msg))
47
+ .catch(err => console.error('Error:', err));
48
+ ```
49
+
50
+ `at` also accepts a Unix millisecond timestamp:
51
+
52
+ ```javascript
53
+ cordova.plugins.alarmNotify.schedule({
54
+ id: 2,
55
+ title: 'Reminder',
56
+ text: 'Check emails',
57
+ at: Date.now() + 5 * 60 * 1000 // 5 minutes from now
58
+ });
59
+ ```
60
+
61
+ **Legacy API (Callbacks):**
62
+
63
+ ```javascript
64
+ cordova.plugins.alarmNotify.schedule(
65
+ 1, // id
66
+ 'Meeting', // title
67
+ 'Team standup', // text
68
+ Date.now() + 60000, // trigger time (ms)
69
+ msg => console.log(msg),
70
+ err => console.error(err)
71
+ );
72
+ ```
73
+
74
+ ### Cancel an Alarm
75
+
76
+ **Modern API (Promise):**
77
+
78
+ ```javascript
79
+ cordova.plugins.alarmNotify.cancel(1)
80
+ .then(msg => console.log('Cancelled:', msg))
81
+ .catch(err => console.error('Error:', err));
82
+ ```
83
+
84
+ **Legacy API (Callbacks):**
85
+
86
+ ```javascript
87
+ cordova.plugins.alarmNotify.cancel(
88
+ 1,
89
+ msg => console.log('Cancelled:', msg),
90
+ err => console.error('Error:', err)
91
+ );
92
+ ```
93
+
94
+ ## Runtime Permission Handling
95
+
96
+ On first use, the plugin may trigger the following system dialogs automatically:
97
+
98
+ - **Android 13+** — "Allow notifications" permission dialog.
99
+ - **Android 12+** — Redirects to the *Alarms & Reminders* settings screen if exact alarm permission is not granted.
100
+ - **All versions** — Requests battery optimization exemption so alarms work reliably in the background.
101
+
102
+ ## TypeScript
103
+
104
+ Type definitions are included:
105
+
106
+ ```typescript
107
+ import { AlarmNotifyPlugin, AlarmOptions } from 'cordova-notify-plugin';
108
+
109
+ declare const cordova: {
110
+ plugins: { alarmNotify: AlarmNotifyPlugin }
111
+ };
112
+
113
+ const options: AlarmOptions = {
114
+ id: 1,
115
+ title: 'Alarm',
116
+ text: 'Wake up!',
117
+ at: new Date()
118
+ };
119
+
120
+ await cordova.plugins.alarmNotify.schedule(options);
121
+ ```
122
+
123
+ ## Notes
124
+
125
+ - Reusing the same `id` overwrites the existing alarm with that id.
126
+ - Alarms with a trigger time in the past are silently ignored on reboot recovery.
127
+ - The plugin stores scheduled alarms in `SharedPreferences` so they can be restored after a reboot.
128
+
129
+ ## License
130
+
131
+ Apache-2.0
package/index.d.ts ADDED
@@ -0,0 +1,66 @@
1
+ export interface AlarmOptions {
2
+ /** Unique alarm identifier. Reusing the same id overwrites the previous alarm. */
3
+ id: number;
4
+ /** Notification title shown in the status bar. */
5
+ title: string;
6
+ /** Notification body text. */
7
+ text: string;
8
+ /** Trigger time as a Date object or Unix millisecond timestamp. */
9
+ at: Date | number;
10
+ }
11
+
12
+ export interface AlarmNotifyPlugin {
13
+ /**
14
+ * Schedule a local alarm notification.
15
+ *
16
+ * @example
17
+ * // Promise
18
+ * await cordova.plugins.alarmNotify.schedule({
19
+ * id: 1,
20
+ * title: 'Meeting',
21
+ * text: 'Team standup',
22
+ * at: new Date('2026-04-17T09:00:00'),
23
+ * });
24
+ *
25
+ * // Callback (legacy)
26
+ * cordova.plugins.alarmNotify.schedule(1, 'Meeting', 'Standup', Date.now() + 60000,
27
+ * msg => console.log(msg),
28
+ * err => console.error(err)
29
+ * );
30
+ */
31
+ schedule(options: AlarmOptions): Promise<string>;
32
+ schedule(
33
+ id: number,
34
+ title: string,
35
+ text: string,
36
+ atMillis: number,
37
+ success: (msg: string) => void,
38
+ error: (err: string) => void
39
+ ): void;
40
+
41
+ /**
42
+ * Cancel a previously scheduled alarm.
43
+ *
44
+ * @example
45
+ * // Promise
46
+ * await cordova.plugins.alarmNotify.cancel(1);
47
+ *
48
+ * // Callback (legacy)
49
+ * cordova.plugins.alarmNotify.cancel(1,
50
+ * msg => console.log(msg),
51
+ * err => console.error(err)
52
+ * );
53
+ */
54
+ cancel(id: number): Promise<string>;
55
+ cancel(
56
+ id: number,
57
+ success: (msg: string) => void,
58
+ error: (err: string) => void
59
+ ): void;
60
+ }
61
+
62
+ declare global {
63
+ interface CordovaPlugins {
64
+ alarmNotify: AlarmNotifyPlugin;
65
+ }
66
+ }
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "cordova-notify-plugin",
3
+ "version": "1.0.1",
4
+ "description": "Cordova plugin to schedule and cancel local alarm notifications on Android. Survives device reboot and works while the app is closed.",
5
+ "main": "www/alarmNotify.js",
6
+ "types": "index.d.ts",
7
+ "cordova": {
8
+ "id": "com.solocode.alarmnotify",
9
+ "platforms": [
10
+ "android"
11
+ ]
12
+ },
13
+ "keywords": [
14
+ "ecosystem:cordova",
15
+ "cordova-android",
16
+ "alarm",
17
+ "notification",
18
+ "local-notification",
19
+ "schedule",
20
+ "background"
21
+ ],
22
+ "files": [
23
+ "plugin.xml",
24
+ "package.json",
25
+ "index.d.ts",
26
+ "www/",
27
+ "src/"
28
+ ],
29
+ "engines": {
30
+ "cordovaDependencies": {
31
+ "1.0.0": {
32
+ "cordova-android": ">=12.0.0",
33
+ "cordova": ">=12.0.0"
34
+ }
35
+ }
36
+ },
37
+ "author": "",
38
+ "license": "MIT",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": ""
42
+ },
43
+ "bugs": {
44
+ "url": ""
45
+ },
46
+ "homepage": ""
47
+ }
package/plugin.xml ADDED
@@ -0,0 +1,52 @@
1
+ <?xml version='1.0' encoding='utf-8'?>
2
+ <plugin id="com.solocode.alarmnotify" version="1.0.0" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
3
+ <name>alarmNotify</name>
4
+
5
+ <js-module name="alarmNotify" src="www/alarmNotify.js">
6
+ <clobbers target="cordova.plugins.alarmNotify" />
7
+ </js-module>
8
+
9
+ <platform name="android">
10
+ <config-file target="res/xml/config.xml" parent="/*">
11
+ <feature name="AlarmNotify">
12
+ <param name="android-package" value="com.solocode.alarmnotify.AlarmNotify" />
13
+ </feature>
14
+ </config-file>
15
+
16
+ <source-file src="src/android/AlarmNotify.java" target-dir="src/com/solocode/alarmnotify" />
17
+ <source-file src="src/android/AlarmReceiver.java" target-dir="src/com/solocode/alarmnotify" />
18
+ <source-file src="src/android/BootReceiver.java" target-dir="src/com/solocode/alarmnotify" />
19
+
20
+ <framework src="androidx.core:core:1.12.0" />
21
+
22
+ <config-file target="AndroidManifest.xml" parent="/manifest">
23
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
24
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
25
+ <!-- Tam zamanlı alarm için (Android 12+ bazı durumlarda gerekebilir) -->
26
+ <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
27
+
28
+ <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
29
+ </config-file>
30
+
31
+ <config-file target="AndroidManifest.xml" parent="/manifest/application">
32
+
33
+ <!-- Alarm tetikleyici receiver -->
34
+ <receiver
35
+ android:name="com.solocode.alarmnotify.AlarmReceiver"
36
+ android:exported="false" />
37
+
38
+ <!-- Reboot sonrası tekrar kuran receiver -->
39
+ <receiver
40
+ android:name="com.solocode.alarmnotify.BootReceiver"
41
+ android:exported="true">
42
+ <intent-filter>
43
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
44
+ </intent-filter>
45
+ </receiver>
46
+
47
+ </config-file>
48
+ </platform>
49
+
50
+
51
+
52
+ </plugin>
@@ -0,0 +1,208 @@
1
+ package com.solocode.alarmnotify;
2
+
3
+ import android.Manifest;
4
+ import android.app.AlarmManager;
5
+ import android.app.PendingIntent;
6
+ import android.content.Context;
7
+ import android.content.Intent;
8
+ import android.content.SharedPreferences;
9
+ import android.content.pm.PackageManager;
10
+ import android.net.Uri;
11
+ import android.os.Build;
12
+ import android.os.PowerManager;
13
+ import android.provider.Settings;
14
+
15
+ import org.apache.cordova.CallbackContext;
16
+ import org.apache.cordova.CordovaPlugin;
17
+ import org.apache.cordova.PermissionHelper;
18
+
19
+ import org.json.JSONArray;
20
+ import org.json.JSONException;
21
+ import org.json.JSONObject;
22
+
23
+ import java.util.HashSet;
24
+ import java.util.Set;
25
+
26
+ public class AlarmNotify extends CordovaPlugin {
27
+
28
+ private static final int REQ_POST_NOTIF = 7001;
29
+
30
+ private static final String PREFS = "AlarmNotifyPrefs";
31
+ private static final String KEY_IDS = "alarm_ids";
32
+ private static final String KEY_ALARM_PREFIX = "alarm_";
33
+
34
+ private CallbackContext pendingCallback;
35
+ private JSONArray pendingArgs;
36
+
37
+ @Override
38
+ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
39
+
40
+ if ("schedule".equals(action)) {
41
+ // Android 13+ bildirim izni
42
+ if (Build.VERSION.SDK_INT >= 33) {
43
+ if (!hasPostNotificationsPermission()) {
44
+ pendingCallback = callbackContext;
45
+ pendingArgs = args;
46
+ PermissionHelper.requestPermission(this, REQ_POST_NOTIF, Manifest.permission.POST_NOTIFICATIONS);
47
+ return true;
48
+ }
49
+ }
50
+ // Android 12'de exact alarm izni kontrolü
51
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
52
+ AlarmManager am = (AlarmManager) cordova.getActivity().getSystemService(Context.ALARM_SERVICE);
53
+ if (!am.canScheduleExactAlarms()) {
54
+ // Kullanıcıyı exact alarm ayarları ekranına yönlendir
55
+ Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM,
56
+ Uri.parse("package:" + cordova.getActivity().getPackageName()));
57
+ cordova.getActivity().startActivity(intent);
58
+ callbackContext.error("EXACT_ALARM_PERMISSION_REQUIRED");
59
+ return true;
60
+ }
61
+ }
62
+ // Pil optimizasyon muafiyeti iste (Doze / agresif üretici optimizasyonlarına karşı)
63
+ requestBatteryExemptionIfNeeded();
64
+ scheduleInternal(args, callbackContext);
65
+ return true;
66
+ }
67
+
68
+ if ("cancel".equals(action)) {
69
+ int id = args.optInt(0, 1);
70
+ cancelAlarm(cordova.getActivity().getApplicationContext(), id);
71
+ removeAlarm(cordova.getActivity().getApplicationContext(), id);
72
+ callbackContext.success("cancelled " + id);
73
+ return true;
74
+ }
75
+
76
+ return false;
77
+ }
78
+
79
+ private boolean hasPostNotificationsPermission() {
80
+ return cordova.getActivity().checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS)
81
+ == PackageManager.PERMISSION_GRANTED;
82
+ }
83
+
84
+ private void requestBatteryExemptionIfNeeded() {
85
+ try {
86
+ PowerManager pm = (PowerManager) cordova.getActivity().getSystemService(Context.POWER_SERVICE);
87
+ String pkg = cordova.getActivity().getPackageName();
88
+ if (!pm.isIgnoringBatteryOptimizations(pkg)) {
89
+ Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
90
+ Uri.parse("package:" + pkg));
91
+ cordova.getActivity().startActivity(intent);
92
+ }
93
+ } catch (Exception ignored) {
94
+ // İzin yoksa veya cihaz desteklemiyorsa sessizce geç
95
+ }
96
+ }
97
+
98
+ @Override
99
+ public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) throws JSONException {
100
+ if (requestCode == REQ_POST_NOTIF) {
101
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
102
+ // Android 12 exact alarm kontrolü de burada tekrarla
103
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
104
+ AlarmManager am = (AlarmManager) cordova.getActivity().getSystemService(Context.ALARM_SERVICE);
105
+ if (!am.canScheduleExactAlarms()) {
106
+ Intent intent = new Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM,
107
+ Uri.parse("package:" + cordova.getActivity().getPackageName()));
108
+ cordova.getActivity().startActivity(intent);
109
+ if (pendingCallback != null) pendingCallback.error("EXACT_ALARM_PERMISSION_REQUIRED");
110
+ pendingCallback = null;
111
+ pendingArgs = null;
112
+ return;
113
+ }
114
+ }
115
+ requestBatteryExemptionIfNeeded();
116
+ scheduleInternal(pendingArgs, pendingCallback);
117
+ } else {
118
+ if (pendingCallback != null) pendingCallback.error("POST_NOTIFICATIONS denied");
119
+ }
120
+ pendingCallback = null;
121
+ pendingArgs = null;
122
+ }
123
+ }
124
+
125
+ private void scheduleInternal(JSONArray args, CallbackContext cb) {
126
+ try {
127
+ int id = args.optInt(0, 1);
128
+ String title = args.optString(1, "Alarm");
129
+ String text = args.optString(2, "Time!");
130
+ long atMillis = args.optLong(3, System.currentTimeMillis() + 5000);
131
+
132
+ Context ctx = cordova.getActivity().getApplicationContext();
133
+ scheduleAlarm(ctx, id, title, text, atMillis);
134
+ saveAlarm(ctx, id, title, text, atMillis);
135
+ cb.success("scheduled " + id + " at " + atMillis);
136
+ } catch (Exception e) {
137
+ cb.error(e.getMessage());
138
+ }
139
+ }
140
+
141
+ // --------- STATIC HELPERS (BootReceiver da kullanacak) ---------
142
+
143
+ public static void scheduleAlarm(Context ctx, int id, String title, String text, long atMillis) {
144
+ Intent intent = new Intent(ctx, AlarmReceiver.class);
145
+ intent.putExtra("id", id);
146
+ intent.putExtra("title", title);
147
+ intent.putExtra("text", text);
148
+
149
+ PendingIntent pi = PendingIntent.getBroadcast(
150
+ ctx, id, intent,
151
+ PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)
152
+ );
153
+
154
+ AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
155
+
156
+ try {
157
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && am.canScheduleExactAlarms()) {
158
+ am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, atMillis, pi);
159
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
160
+ am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, atMillis, pi);
161
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
162
+ am.setExact(AlarmManager.RTC_WAKEUP, atMillis, pi);
163
+ } else {
164
+ am.set(AlarmManager.RTC_WAKEUP, atMillis, pi);
165
+ }
166
+ } catch (SecurityException se) {
167
+ am.set(AlarmManager.RTC_WAKEUP, atMillis, pi);
168
+ }
169
+ }
170
+
171
+ public static void cancelAlarm(Context ctx, int id) {
172
+ Intent intent = new Intent(ctx, AlarmReceiver.class);
173
+ PendingIntent pi = PendingIntent.getBroadcast(
174
+ ctx, id, intent,
175
+ PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0)
176
+ );
177
+ AlarmManager am = (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
178
+ am.cancel(pi);
179
+ }
180
+
181
+ private static void saveAlarm(Context ctx, int id, String title, String text, long atMillis) throws JSONException {
182
+ SharedPreferences sp = ctx.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
183
+ Set<String> ids = new HashSet<>(sp.getStringSet(KEY_IDS, new HashSet<>()));
184
+ ids.add(String.valueOf(id));
185
+ JSONObject o = new JSONObject();
186
+ o.put("id", id); o.put("title", title); o.put("text", text); o.put("atMillis", atMillis);
187
+ sp.edit().putStringSet(KEY_IDS, ids).putString(KEY_ALARM_PREFIX + id, o.toString()).apply();
188
+ }
189
+
190
+ private static void removeAlarm(Context ctx, int id) {
191
+ SharedPreferences sp = ctx.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
192
+ Set<String> ids = new HashSet<>(sp.getStringSet(KEY_IDS, new HashSet<>()));
193
+ ids.remove(String.valueOf(id));
194
+ sp.edit().putStringSet(KEY_IDS, ids).remove(KEY_ALARM_PREFIX + id).apply();
195
+ }
196
+
197
+ public static Set<String> getSavedAlarmIds(Context ctx) {
198
+ SharedPreferences sp = ctx.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
199
+ return new HashSet<>(sp.getStringSet(KEY_IDS, new HashSet<>()));
200
+ }
201
+
202
+ public static JSONObject getSavedAlarm(Context ctx, String idStr) {
203
+ SharedPreferences sp = ctx.getSharedPreferences(PREFS, Context.MODE_PRIVATE);
204
+ String raw = sp.getString(KEY_ALARM_PREFIX + idStr, null);
205
+ if (raw == null) return null;
206
+ try { return new JSONObject(raw); } catch (Exception e) { return null; }
207
+ }
208
+ }
@@ -0,0 +1,44 @@
1
+ package com.solocode.alarmnotify;
2
+
3
+ import android.app.NotificationChannel;
4
+ import android.app.NotificationManager;
5
+ import android.content.BroadcastReceiver;
6
+ import android.content.Context;
7
+ import android.content.Intent;
8
+ import android.os.Build;
9
+
10
+ import androidx.core.app.NotificationCompat;
11
+
12
+ public class AlarmReceiver extends BroadcastReceiver {
13
+
14
+ private static final String CHANNEL_ID = "alarm_notify_channel";
15
+
16
+ @Override
17
+ public void onReceive(Context context, Intent intent) {
18
+ int id = intent.getIntExtra("id", 1);
19
+ String title = intent.getStringExtra("title");
20
+ String text = intent.getStringExtra("text");
21
+
22
+ NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
23
+
24
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
25
+ NotificationChannel ch = new NotificationChannel(
26
+ CHANNEL_ID,
27
+ "Alarm Notifications",
28
+ NotificationManager.IMPORTANCE_HIGH
29
+ );
30
+ nm.createNotificationChannel(ch);
31
+ }
32
+
33
+ int iconRes = context.getApplicationInfo().icon;
34
+
35
+ NotificationCompat.Builder b = new NotificationCompat.Builder(context, CHANNEL_ID)
36
+ .setSmallIcon(iconRes)
37
+ .setContentTitle(title != null ? title : "Alarm")
38
+ .setContentText(text != null ? text : "Time!")
39
+ .setAutoCancel(true)
40
+ .setPriority(NotificationCompat.PRIORITY_HIGH);
41
+
42
+ nm.notify(id, b.build());
43
+ }
44
+ }
@@ -0,0 +1,38 @@
1
+ package com.solocode.alarmnotify;
2
+
3
+ import android.content.BroadcastReceiver;
4
+ import android.content.Context;
5
+ import android.content.Intent;
6
+
7
+ import org.json.JSONObject;
8
+
9
+ import java.util.Set;
10
+
11
+ public class BootReceiver extends BroadcastReceiver {
12
+
13
+ @Override
14
+ public void onReceive(Context context, Intent intent) {
15
+ if (intent == null) return;
16
+ if (!Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) return;
17
+
18
+ Set<String> ids = AlarmNotify.getSavedAlarmIds(context);
19
+ long now = System.currentTimeMillis();
20
+
21
+ for (String idStr : ids) {
22
+ try {
23
+ JSONObject o = AlarmNotify.getSavedAlarm(context, idStr);
24
+ if (o == null) continue;
25
+
26
+ int id = o.optInt("id", 1);
27
+ String title = o.optString("title", "Alarm");
28
+ String text = o.optString("text", "Time!");
29
+ long atMillis = o.optLong("atMillis", now);
30
+
31
+ // geçmişte kaldıysa istersen hemen göster, ya da atla:
32
+ if (atMillis < now) continue;
33
+
34
+ AlarmNotify.scheduleAlarm(context, id, title, text, atMillis);
35
+ } catch (Exception ignored) {}
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,66 @@
1
+ var exec = require('cordova/exec');
2
+
3
+ /**
4
+ * Schedule a local alarm notification.
5
+ *
6
+ * Modern usage (returns Promise):
7
+ * alarmNotify.schedule({ id: 1, title: 'Meeting', text: 'Standup', at: new Date() })
8
+ *
9
+ * Legacy usage (callbacks):
10
+ * alarmNotify.schedule(1, 'Meeting', 'Standup', Date.now() + 60000, onSuccess, onError)
11
+ *
12
+ * @param {Object|number} optionsOrId Options object or alarm id (legacy).
13
+ * @param {string} [title] Notification title (legacy).
14
+ * @param {string} [text] Notification body (legacy).
15
+ * @param {number} [atMillis] Trigger time as Unix ms timestamp (legacy).
16
+ * @param {Function} [success] Success callback (legacy).
17
+ * @param {Function} [error] Error callback (legacy).
18
+ * @returns {Promise<string>|undefined}
19
+ */
20
+ exports.schedule = function (optionsOrId, title, text, atMillis, success, error) {
21
+ var id, _title, _text, _at;
22
+
23
+ if (optionsOrId !== null && typeof optionsOrId === 'object') {
24
+ // Modern: options object
25
+ id = optionsOrId.id != null ? optionsOrId.id : 1;
26
+ _title = optionsOrId.title != null ? optionsOrId.title : 'Alarm';
27
+ _text = optionsOrId.text != null ? optionsOrId.text : '';
28
+ _at = optionsOrId.at instanceof Date
29
+ ? optionsOrId.at.getTime()
30
+ : (optionsOrId.at != null ? optionsOrId.at : Date.now());
31
+
32
+ return new Promise(function (resolve, reject) {
33
+ exec(resolve, reject, 'AlarmNotify', 'schedule', [id, _title, _text, _at]);
34
+ });
35
+ }
36
+
37
+ // Legacy: positional args + callbacks
38
+ id = optionsOrId;
39
+ _title = title;
40
+ _text = text;
41
+ _at = atMillis;
42
+ exec(success, error, 'AlarmNotify', 'schedule', [id, _title, _text, _at]);
43
+ };
44
+
45
+ /**
46
+ * Cancel a previously scheduled alarm.
47
+ *
48
+ * Modern usage (returns Promise):
49
+ * alarmNotify.cancel(1)
50
+ *
51
+ * Legacy usage (callbacks):
52
+ * alarmNotify.cancel(1, onSuccess, onError)
53
+ *
54
+ * @param {number} id Alarm id to cancel.
55
+ * @param {Function} [success] Success callback (legacy).
56
+ * @param {Function} [error] Error callback (legacy).
57
+ * @returns {Promise<string>|undefined}
58
+ */
59
+ exports.cancel = function (id, success, error) {
60
+ if (typeof success !== 'function' && typeof error !== 'function') {
61
+ return new Promise(function (resolve, reject) {
62
+ exec(resolve, reject, 'AlarmNotify', 'cancel', [id]);
63
+ });
64
+ }
65
+ exec(success, error, 'AlarmNotify', 'cancel', [id]);
66
+ };