Skip to content

Commit

Permalink
Add broadcast reciver to reschedule reminders on device reboot or tim…
Browse files Browse the repository at this point in the history
…e change

Signed-off-by: starry-shivam <krshivam24@proton.me>
  • Loading branch information
starry-shivam committed Jul 13, 2023
1 parent 44e9440 commit 926819e
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 34 deletions.
36 changes: 23 additions & 13 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application
android:name=".GreenStashApp"
Expand All @@ -27,6 +27,15 @@
</intent-filter>
</activity>

<activity
android:name=".widget.configuration.WidgetConfigActivity"
android:exported="false"
android:theme="@style/Theme.GreenStash">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>

<receiver
android:name=".widget.GoalWidget"
android:exported="true">
Expand All @@ -38,28 +47,29 @@
android:resource="@xml/goal_widget_info" />
</receiver>

<activity
android:name=".widget.configuration.WidgetConfigActivity"
android:exported="false"
android:theme="@style/Theme.GreenStash">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>

<receiver android:name=".reminder.AlarmReceiver"
<receiver
android:name=".reminder.AlarmReceiver"
android:enabled="true"
android:exported="false"/>
android:exported="false" />

<receiver
android:name=".reminder.BootReceiver"
android:enabled="true"
android:exported="false">

<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

<receiver
android:name=".reminder.DateTimeChangeReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
<action android:name="android.intent.action.TIME_SET" />
<action android:name="android.intent.action.DATE_CHANGED" />
</intent-filter>
</receiver>

</application>
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/java/com/starry/greenstash/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
package com.starry.greenstash

import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.activity.compose.setContent
Expand All @@ -51,7 +50,6 @@ import androidx.lifecycle.ViewModelProvider
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.starry.greenstash.database.core.AppDatabase
import com.starry.greenstash.reminder.ReminderNotificationSender
import com.starry.greenstash.ui.navigation.NavGraph
import com.starry.greenstash.ui.screens.settings.viewmodels.SettingsViewModel
import com.starry.greenstash.ui.screens.settings.viewmodels.ThemeMode
Expand Down
22 changes: 15 additions & 7 deletions app/src/main/java/com/starry/greenstash/database/goal/GoalDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,41 @@ interface GoalDao {

@Transaction
@Query("SELECT * FROM saving_goal")
fun getAllGoals(): LiveData<List<GoalWithTransactions>>
suspend fun getAllGoals(): List<GoalWithTransactions>

@Transaction
@Query("SELECT * FROM saving_goal")
fun getAllGoalsAsLiveData(): LiveData<List<GoalWithTransactions>>

@Query("SELECT * FROM saving_goal WHERE goalId = :goalId")
suspend fun getGoalById(goalId: Long): Goal?

@Transaction
@Query("SELECT * FROM saving_goal WHERE goalId = :goalId")
suspend fun getGoalWithTransactionById(goalId: Long): GoalWithTransactions?

@Transaction
@Query(
"SELECT * FROM saving_goal ORDER BY " +
"CASE WHEN :sortOrder = 1 THEN title END ASC, " +
"CASE WHEN :sortOrder = 2 THEN title END DESC "
)
fun getAllGoalsByTitle(sortOrder: Int): Flow<List<GoalWithTransactions>>

@Transaction
@Query(
"SELECT * FROM saving_goal ORDER BY " +
"CASE WHEN :sortOrder = 1 THEN targetAmount END ASC, " +
"CASE WHEN :sortOrder = 2 THEN targetAmount END DESC "
)
fun getAllGoalsByAmount(sortOrder: Int): Flow<List<GoalWithTransactions>>

@Transaction
@Query(
"SELECT * FROM saving_goal ORDER BY " +
"CASE WHEN :sortOrder = 1 THEN priority END ASC, " +
"CASE WHEN :sortOrder = 2 THEN priority END DESC "
)
fun getAllGoalsByPriority(sortOrder: Int): Flow<List<GoalWithTransactions>>

@Query("SELECT * FROM saving_goal WHERE goalId = :goalId")
fun getGoalById(goalId: Long): Goal?

@Transaction
@Query("SELECT * FROM saving_goal WHERE goalId = :goalId")
fun getGoalWithTransactionById(goalId: Long): GoalWithTransactions?
}
32 changes: 29 additions & 3 deletions app/src/main/java/com/starry/greenstash/reminder/BootReceiver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,37 @@ package com.starry.greenstash.reminder
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.ui.ExperimentalComposeUiApi
import com.starry.greenstash.database.goal.GoalDao
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject

@ExperimentalMaterial3Api
@ExperimentalAnimationApi
@ExperimentalComposeUiApi
@ExperimentalFoundationApi
@ExperimentalMaterialApi
@AndroidEntryPoint
class BootReceiver : BroadcastReceiver() {

@Inject
lateinit var goalDao: GoalDao

class BootReceiver:BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
if (intent?.action == "android.intent.action.BOOT_COMPLETED") {
//TODO: Schedule reminders here.
if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
val coroutineScope = CoroutineScope(Dispatchers.IO)
coroutineScope.launch {
val allGoals = goalDao.getAllGoals()
val reminderManager = ReminderManager(context)
reminderManager.scheduleReminderForAllGoals(allGoals)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.starry.greenstash.reminder

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.ui.ExperimentalComposeUiApi
import com.starry.greenstash.database.goal.GoalDao
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import javax.inject.Inject

@ExperimentalMaterial3Api
@ExperimentalAnimationApi
@ExperimentalComposeUiApi
@ExperimentalFoundationApi
@ExperimentalMaterialApi
@AndroidEntryPoint
class DateTimeChangeReceiver : BroadcastReceiver() {

@Inject
lateinit var goalDao: GoalDao

override fun onReceive(context: Context, intent: Intent?) {
if (intent?.action == Intent.ACTION_TIME_CHANGED
|| intent?.action == Intent.ACTION_TIMEZONE_CHANGED
|| intent?.action == Intent.ACTION_DATE_CHANGED
) {
val coroutineScope = CoroutineScope(Dispatchers.IO)
coroutineScope.launch {
val allGoals = goalDao.getAllGoals()
val reminderManager = ReminderManager(context)
reminderManager.scheduleReminderForAllGoals(allGoals)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.ui.ExperimentalComposeUiApi
import com.starry.greenstash.database.core.GoalWithTransactions
import com.starry.greenstash.database.goal.GoalPriority
import java.util.Calendar
import java.util.Locale


@ExperimentalMaterial3Api
@ExperimentalAnimationApi
@ExperimentalComposeUiApi
Expand Down Expand Up @@ -95,6 +97,21 @@ class ReminderManager(private val context: Context) {
scheduleReminder(goalId, priority)
}

/**
* Schedules reminder for goals which have reminder enabled
* by calling the [scheduleReminder] function internally.
*/
fun scheduleReminderForAllGoals(allGoals: List<GoalWithTransactions>) {
Log.d(TAG, "Scheduling reminders for goals with reminder.")
allGoals.forEach { goalItem ->
val goal = goalItem.goal
if (goal.reminder && isReminderSet(goal.goalId)) {
scheduleReminder(goal.goalId, goal.priority)
}
}
Log.d(TAG, "Scheduled reminders for goals with reminder.")
}

private fun createReminderIntent(goalId: Long, flags: Int) =
Intent(context.applicationContext, AlarmReceiver::class.java)
.apply { putExtra(INTENT_EXTRA_GOAL_ID, goalId) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class WidgetConfigViewModel @Inject constructor(
private val goalDao: GoalDao,
private val widgetDao: WidgetDao
) : ViewModel() {
val allGoals: LiveData<List<GoalWithTransactions>> = goalDao.getAllGoals()
val allGoals: LiveData<List<GoalWithTransactions>> = goalDao.getAllGoalsAsLiveData()

/**
* Maps widget id with the selected saving goal id
Expand Down
13 changes: 9 additions & 4 deletions app/src/main/res/drawable/ic_notification_deposit.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#000000"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z" />
</vector>
13 changes: 9 additions & 4 deletions app/src/main/res/drawable/ic_reminder_notification.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19.83,7.5l-2.27,-2.27c0.07,-0.42 0.18,-0.81 0.32,-1.15C17.96,3.9 18,3.71 18,3.5C18,2.67 17.33,2 16.5,2c-1.64,0 -3.09,0.79 -4,2l-5,0C4.46,4 2,6.46 2,9.5S4.5,21 4.5,21l5.5,0v-2h2v2l5.5,0l1.68,-5.59L22,14.47V7.5H19.83zM13,9H8V7h5V9zM16,11c-0.55,0 -1,-0.45 -1,-1c0,-0.55 0.45,-1 1,-1s1,0.45 1,1C17,10.55 16.55,11 16,11z"/>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#000000"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M19.83,7.5l-2.27,-2.27c0.07,-0.42 0.18,-0.81 0.32,-1.15C17.96,3.9 18,3.71 18,3.5C18,2.67 17.33,2 16.5,2c-1.64,0 -3.09,0.79 -4,2l-5,0C4.46,4 2,6.46 2,9.5S4.5,21 4.5,21l5.5,0v-2h2v2l5.5,0l1.68,-5.59L22,14.47V7.5H19.83zM13,9H8V7h5V9zM16,11c-0.55,0 -1,-0.45 -1,-1c0,-0.55 0.45,-1 1,-1s1,0.45 1,1C17,10.55 16.55,11 16,11z" />
</vector>

0 comments on commit 926819e

Please sign in to comment.