diff --git a/Alarm.tsx b/Alarm.tsx
index 7b70e1d..ea9408b 100644
--- a/Alarm.tsx
+++ b/Alarm.tsx
@@ -15,14 +15,14 @@ export default function Alarm({onClose}: {onClose: () => void}) {
if (ms <= 0) return;
let secondsLeft = ms / 1000;
console.log({secondsLeft});
- setSeconds(secondsLeft % 60);
+ setSeconds(Math.floor(secondsLeft % 60));
setMinutes(Math.floor(secondsLeft / 60));
intervalId = setInterval(() => {
console.log({seconds, secondsLeft});
secondsLeft--;
if (secondsLeft <= 0) return clearInterval(intervalId);
- setSeconds(Math.ceil(secondsLeft % 60));
+ setSeconds(Math.floor(secondsLeft % 60));
setMinutes(Math.floor(secondsLeft / 60));
}, 1000);
});
diff --git a/Home.tsx b/Home.tsx
index 2ad7929..aa95202 100644
--- a/Home.tsx
+++ b/Home.tsx
@@ -3,19 +3,17 @@ import {NativeStackScreenProps} from '@react-navigation/native-stack';
import React, {useEffect, useState} from 'react';
import {
FlatList,
+ NativeModules,
SafeAreaView,
StyleSheet,
TextInput,
Vibration,
View,
} from 'react-native';
-import BackgroundTimer from 'react-native-background-timer';
import {Button, List} from 'react-native-paper';
-import PushNotification from 'react-native-push-notification';
import Sound from 'react-native-sound';
import Alarm from './Alarm';
import {RootStackParamList} from './App';
-import {ALARM} from './channels';
import {getDb} from './db';
import EditSet from './EditSet';
@@ -84,20 +82,8 @@ export default function Home({
const milliseconds = Number(minutes) * 60 * 1000 + Number(seconds) * 1000;
const when = new Date();
when.setTime(when.getTime() + milliseconds);
+ NativeModules.AlarmModule.timer(milliseconds);
await AsyncStorage.setItem('nextAlarm', when.toISOString());
- const timeoutId = BackgroundTimer.setTimeout(() => {
- alarm.play(_onEnd => Vibration.cancel());
- Vibration.vibrate([0, 400, 600], /*repeat=*/ true);
- PushNotification.localNotification({
- message: 'Timer up',
- channelId: ALARM,
- vibrate: true,
- });
- }, Number(milliseconds));
- BackgroundTimer.clearTimeout(
- Number(await AsyncStorage.getItem('timeoutId')),
- );
- await AsyncStorage.setItem('timeoutId', timeoutId.toString());
};
const close = () => {
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 063040e..461162d 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -264,6 +264,24 @@ android {
}
dependencies {
+ def work_version = "2.7.1"
+ // (Java only)
+ implementation "androidx.work:work-runtime:$work_version"
+
+ // Kotlin + coroutines
+ implementation "androidx.work:work-runtime-ktx:$work_version"
+
+ // optional - RxJava2 support
+ implementation "androidx.work:work-rxjava2:$work_version"
+
+ // optional - GCMNetworkManager support
+ implementation "androidx.work:work-gcm:$work_version"
+
+ // optional - Test helpers
+ androidTestImplementation "androidx.work:work-testing:$work_version"
+ // optional - Multiprocess support
+ implementation "androidx.work:work-multiprocess:$work_version"
+
implementation fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDynamicVersion
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 96176d3..989f592 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
+
createViewManagers(@NonNull ReactApplicationContext reactContext) {
+ return Collections.emptyList();
+ }
+
+ @NonNull
+ @Override
+ public List createNativeModules(
+ @NonNull ReactApplicationContext reactContext) {
+ List modules = new ArrayList<>();
+
+ modules.add(new AlarmModule(reactContext));
+
+ return modules;
+ }
+
+}
diff --git a/android/app/src/main/java/com/massive/AlarmWorker.java b/android/app/src/main/java/com/massive/AlarmWorker.java
new file mode 100644
index 0000000..b6c47da
--- /dev/null
+++ b/android/app/src/main/java/com/massive/AlarmWorker.java
@@ -0,0 +1,64 @@
+package com.massive;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.os.Build;
+import android.os.Vibrator;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
+import androidx.work.Worker;
+import androidx.work.WorkerParameters;
+
+public class AlarmWorker extends Worker {
+ private static final String CHANNEL_ID = "MassiveAlarms";
+
+ public AlarmWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
+ super(context, workerParams);
+ }
+
+ @NonNull
+ @Override
+ public Result doWork() {
+ Log.d("AlarmWorker", "Doing work...");
+ createNotificationChannel();
+ Intent intent = new Intent(getApplicationContext(), AlarmModule.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_IMMUTABLE);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
+ .setSmallIcon(R.drawable.autofill_inline_suggestion_chip_background)
+ .setContentTitle("Rest complete.")
+ .setContentText("Break time is over!")
+ .setContentIntent(pendingIntent)
+ .setAutoCancel(true)
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT);
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplicationContext());
+ notificationManager.notify(1, builder.build());
+ MediaPlayer mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.argon);
+ mediaPlayer.start(); // no need to call prepare(); create() does that for you
+ Vibrator vibrator = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
+ vibrator.vibrate(400);
+ return Result.success();
+ }
+
+ private void createNotificationChannel() {
+ Log.d("AlarmWorker", "Creating notification channel...");
+ // Create the NotificationChannel, but only on API 26+ because
+ // the NotificationChannel class is new and not in the support library
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ int importance = NotificationManager.IMPORTANCE_DEFAULT;
+ NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "MassiveAlarms", importance);
+ channel.setDescription("Alarms for the Massive application");
+ // Register the channel with the system; you can't change the importance
+ // or other notification behaviors after this
+ NotificationManager notificationManager = getApplicationContext().getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(channel);
+ }
+ }
+}
diff --git a/android/app/src/main/java/com/massive/MainApplication.java b/android/app/src/main/java/com/massive/MainApplication.java
index 6b40f3a..3c5816b 100644
--- a/android/app/src/main/java/com/massive/MainApplication.java
+++ b/android/app/src/main/java/com/massive/MainApplication.java
@@ -28,6 +28,7 @@ public class MainApplication extends Application implements ReactApplication {
@SuppressWarnings("UnnecessaryLocalVariable")
List packages = new PackageList(this).getPackages();
packages.add(new SQLitePluginPackage());
+ packages.add(new AlarmPackage());
return packages;
}