I'm creating a Habit Tracker with Firebase that has the option of remembering an hour and minute of the day to show a notification of the habit you created, the problem is when you create a new habit the notification replaces the old hour and minute warning.
I don't want multiple notifications, but use a single notification to show a message to check the habit.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var notificationHelper: NotificationHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Thread.sleep(2000)
installSplashScreen()
notificationHelper = NotificationHelper(applicationContext)
notificationHelper.createNotificationChannel()//create notification
HabitReminderReceiver
class HabitReminderReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val notification = buildNotification(context, intent)
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.notify(DataBaseConstants.NOTIFICATION.notificationID, notification)
}
private fun buildNotification(context: Context, intent: Intent): Notification {
val message = intent.getStringExtra(DataBaseConstants.NOTIFICATION.messageExtra)
return Notification.Builder(context, DataBaseConstants.NOTIFICATION.channelID)
.setSmallIcon(R.drawable.baseline_add_alert_24)
.setContentText(message)
.build()
}
}
NotificationHelper to create channel in MainActivity and scheduleNotification
class NotificationHelper(private val context: Context) {
fun createNotificationChannel() {
Log.i("NotificationHelper", "Notification Created ")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
DataBaseConstants.NOTIFICATION.channelID,
DataBaseConstants.NOTIFICATION.channelName,
NotificationManager.IMPORTANCE_DEFAULT
)
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
fun scheduleNotification(context: Context, intent: Intent) {
//get hour and minute from reminder of habit
val hour = intent.getIntExtra(DataBaseConstants.NOTIFICATION.HOUR, -1)
val minute = intent.getIntExtra(DataBaseConstants.NOTIFICATION.MINUTE, -1)
Log.i("NotificationHelper", "$hour: $minute")
val pendingIntent = PendingIntent.getBroadcast(
context,
DataBaseConstants.NOTIFICATION.notificationID,//Use the unique notification ID as the requestCode
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val calendar = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, hour)
set(Calendar.MINUTE, minute)
set(Calendar.SECOND, 0)
}
val time = calendar.timeInMillis // timeInMillis with reminder hour and minute
Log.i(DataBaseConstants.TAG.ADD_HABIT_FORM_ACTIVITY, "Time in millis: $time")
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP, time, AlarmManager.INTERVAL_DAY, pendingIntent
)
}
}
Class addHabitFormActivity who add new habit and use NotificationHelper to schedule reminder
private lateinit var notificationHelper: NotificationHelper
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
notificationHelper = NotificationHelper(context = applicationContext)
buttonCreateHabit.setOnClickListener {
//class habit to pass name, user id, icon, reminder with hour and minute...
habit = Habit(
"",//id empty
editName.text.toString(),
editDesc.text.toString(),
FirebaseAuthManager.getCurrentUser?.uid.toString(),
reminder,
dataEnd,
icon,
rangeOptionEnumClass,
goalType,
durationTimer,
arrayListOf()
)
habit.save()//save into firebase the habit
Toast.makeText(
applicationContext,
getString(R.string.save_success),
Toast.LENGTH_SHORT).show()//Toast saved
if (!editReminderTimepick.text.isEmpty()) {
//add hour and minute from class Reminder and name of the habit
var intent = Intent(applicationContext,HabitReminderReceiver::class.java)
intent.putExtra(DataBaseConstants.NOTIFICATION.HOUR, reminder.hour)
intent.putExtra(DataBaseConstants.NOTIFICATION.MINUTE, reminder.minute)
intent.putExtra(DataBaseConstants.NOTIFICATION.messageExtra, habit.name)
notificationHelper.scheduleNotification(this, intent)
}
finish() // finish addHabitFormActivity
}
class DataBaseConstants private constructor() {
object NOTIFICATION {
const val notificationID = 1
const val channelID = "channel1"
const val channelName = "channelName"
const val titleExtra = "titleExtra"
const val messageExtra = "messageExtra"
const val HOUR = "hour"
const val MINUTE = "minute"
}
}
class Reminder {
var enable: Boolean? = false
var hour: Int? = null
var minute: Int? = null
var days: Weekday = Weekday()
}
Manifest
<receiver android:name=".utils.HabitReminderReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
I found how to solve this:
In the HabitReminderReceiver in onReceive I create a variable that is always show 1 notification fixed.
In NotificationHelper a variable habitId that has a hashCode of the Firebase habit id and when the hour and minute reminder is repeated it uses the same notification set in HabiReminderReceive to display, and this does not create multiple notification and updates the same notification with new habit.