Make AlarmModule work

This commit is contained in:
Brandon Presley 2022-07-04 13:41:44 +12:00
parent c6a43b7c83
commit 00a801b44a
7 changed files with 167 additions and 91 deletions

View File

@ -1,29 +1,33 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.massive">
package="com.massive">
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme">
<meta-data android:name="com.dieam.reactnativepushnotification.notification_foreground" android:value="false"/>
<activity
android:name=".MainActivity"
android:name=".MainApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme"
android:dataExtractionRules="@xml/data_extraction_rules">
<meta-data
android:name="com.dieam.reactnativepushnotification.notification_foreground"
android:value="false" />
<activity
android:name=".MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:exported="true"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:exported="true" android:process=":remote" android:name=".MyBroadcastReceiver" />
</application>
</manifest>

View File

@ -1,12 +1,19 @@
package com.massive; // replace com.your-app-name with your apps name
import static android.content.Context.ALARM_SERVICE;
import android.app.AlarmManager;
import android.app.Notification;
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.SystemClock;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
@ -24,6 +31,8 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.time.Duration;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
@ -42,12 +51,15 @@ public class AlarmModule extends ReactContextBaseJavaModule {
@RequiresApi(api = Build.VERSION_CODES.O)
@ReactMethod(isBlockingSynchronousMethod = true)
public void timer(int milliseconds) {
WorkRequest request = new PeriodicWorkRequest.Builder(
AlarmWorker.class, milliseconds, TimeUnit.MILLISECONDS
)
.build();
Log.d("AlarmModule", "Queue alarm for " + milliseconds + " delay");
WorkManager.getInstance(getReactApplicationContext())
.enqueue(request);
Intent intent = new Intent(getReactApplicationContext(), MyBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getReactApplicationContext(), 69, intent, PendingIntent.FLAG_IMMUTABLE);
AlarmManager alarmManager = (AlarmManager) getReactApplicationContext().getSystemService(ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Log.d("AlarmModule", "Can schedule: " + alarmManager.canScheduleExactAlarms());
}
AlarmManager.AlarmClockInfo info = new AlarmManager.AlarmClockInfo(System.currentTimeMillis() + milliseconds, pendingIntent);
alarmManager.setAlarmClock(info, pendingIntent);
}
}

View File

@ -1,64 +0,0 @@
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);
}
}
}

View File

@ -0,0 +1,67 @@
package com.massive;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
public class MyBroadcastReceiver extends BroadcastReceiver {
private static final String CHANNEL_ID = "MassiveAlarm";
private static final int ALARM_ID = 59;
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onReceive(Context context, Intent intent) {
Log.d("MyBroadcastReceiver", "Received intent for BroadcastReceiver.");
long[] pattern = {0, 300, 200, 300, 200};
int[] amplitudes = {VibrationEffect.DEFAULT_AMPLITUDE, VibrationEffect.DEFAULT_AMPLITUDE, VibrationEffect.DEFAULT_AMPLITUDE, VibrationEffect.DEFAULT_AMPLITUDE, VibrationEffect.DEFAULT_AMPLITUDE};
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(VibrationEffect.createWaveform(pattern, amplitudes, 0));
} else {
//deprecated in API 26
vibrator.vibrate(500);
}
createNotificationChannel(context);
Intent contentIntent = new Intent(context.getApplicationContext(), MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, contentIntent, PendingIntent.FLAG_IMMUTABLE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.rn_edit_text_material)
.setContentTitle("Rest")
.setContentText("Break times over!")
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setCategory(NotificationCompat.CATEGORY_ALARM)
.setPriority(NotificationCompat.PRIORITY_HIGH);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(ALARM_ID, builder.build());
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.argon);
mediaPlayer.start();
}
private void createNotificationChannel(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, importance);
channel.setDescription("Alarms for rest timings.");
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
}

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!--
TODO: Use <include> and <exclude> to control what is backed up.
The domain can be file, database, sharedpref, external or root.
Examples:
<include domain="file" path="file_to_include"/>
<exclude domain="file" path="file_to_exclude"/>
<include domain="file" path="include_folder"/>
<exclude domain="file" path="include_folder/file_to_exclude"/>
<exclude domain="file" path="exclude_folder"/>
<include domain="file" path="exclude_folder/file_to_include"/>
<include domain="sharedpref" path="include_shared_pref1.xml"/>
<include domain="database" path="db_name/file_to_include"/>
<exclude domain="database" path="db_name/include_folder/file_to_exclude"/>
<include domain="external" path="file_to_include"/>
<exclude domain="external" path="file_to_exclude"/>
<include domain="root" path="file_to_include"/>
<exclude domain="root" path="file_to_exclude"/>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

View File

@ -14,6 +14,7 @@
"@react-native-async-storage/async-storage": "^1.17.7",
"@react-native-community/push-notification-ios": "^1.10.1",
"@react-navigation/bottom-tabs": "^6.3.1",
"@react-navigation/material-top-tabs": "^6.2.1",
"@react-navigation/native": "^6.0.10",
"@react-navigation/native-stack": "^6.6.2",
"@types/react-native-background-timer": "^2.0.0",
@ -25,6 +26,7 @@
"react-native": "0.69.1",
"react-native-background-timer": "^2.4.1",
"react-native-gesture-handler": "^2.5.0",
"react-native-pager-view": "^5.4.24",
"react-native-paper": "^4.12.2",
"react-native-push-notification": "^8.1.1",
"react-native-reanimated": "^2.9.0",
@ -32,6 +34,7 @@
"react-native-screens": "^3.14.0",
"react-native-sound": "^0.11.2",
"react-native-sqlite-storage": "^6.0.1",
"react-native-tab-view": "^3.1.1",
"react-native-vector-icons": "^9.2.0"
},
"devDependencies": {

View File

@ -1650,6 +1650,14 @@
resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.3.tgz#9f56b650a9a1a8263a271628be7342c8121d1788"
integrity sha512-Lv2lR7si5gNME8dRsqz57d54m4FJtrwHRjNQLOyQO546ZxO+g864cSvoLC6hQedQU0+IJnPTsZiEI2hHqfpEpw==
"@react-navigation/material-top-tabs@^6.2.1":
version "6.2.1"
resolved "https://registry.yarnpkg.com/@react-navigation/material-top-tabs/-/material-top-tabs-6.2.1.tgz#747d17bd0138a7d50c791e9cce1adc350904f67d"
integrity sha512-fGy2+/7cUAyrZUPUhzKUttA4avK5Z2FrNk0LRI04hRlAVqs5DYpnaQGkegGeOGwKmnxaVCjCVPr+KoEroyqduw==
dependencies:
color "^3.1.3"
warn-once "^0.1.0"
"@react-navigation/native-stack@^6.6.2":
version "6.6.2"
resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.6.2.tgz#09e696ad72299872f4c5c1e5b1ad309869853628"
@ -6676,6 +6684,11 @@ react-native-iphone-x-helper@^1.3.1:
resolved "https://registry.yarnpkg.com/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz#20c603e9a0e765fd6f97396638bdeb0e5a60b010"
integrity sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg==
react-native-pager-view@^5.4.24:
version "5.4.24"
resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-5.4.24.tgz#8626e757ddc55e41eca66d2f8a8a75aec54591ee"
integrity sha512-dRMB7i3B+mu4NCeIN6gqbR/kC/rr2wzqO0gisXDdJwJr78G24sWoTNpLEDFo3G8TFHY9nTMutVl5CUvkN2dp6g==
react-native-paper@^4.12.2:
version "4.12.2"
resolved "https://registry.yarnpkg.com/react-native-paper/-/react-native-paper-4.12.2.tgz#31ed8011afd994d54dd403ed0099295fc1616d26"
@ -6727,6 +6740,11 @@ react-native-sqlite-storage@^6.0.1:
resolved "https://registry.yarnpkg.com/react-native-sqlite-storage/-/react-native-sqlite-storage-6.0.1.tgz#ce6a6b852f07abbea68658d5363818c8bef45dfb"
integrity sha512-1tDFjrint6X6qSYKf3gDyz+XB+X79jfiL6xTugKHPRtF0WvqMtVgdLuNqZunIXjNEvNtNVEbXaeZ6MsguFu00A==
react-native-tab-view@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-3.1.1.tgz#1f8d7a835ab4f5b1b1407ec8dddc1053b53fa3c6"
integrity sha512-M5pRN6utQfytKWoKlKVzg5NbkYu308qNoW1khGTtEOTs1k14p2dHJ/BWOJoJYHKbPVUyZldbG9MFT7gUl4YHnw==
react-native-vector-icons@^9.2.0:
version "9.2.0"
resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-9.2.0.tgz#3c0c82e95defd274d56363cbe8fead8d53167ebd"