I have a method getRandomWordForNotification in viewModel(watch ListFragment) which returns random word from database. And I want to show returned word and its translation in daily notification. Is there any way to pass parameters to AlarmReceiver? Or how can I pass returned word into notification and update it on daily babsis?
Fragment where viewmodel is invoked:
@AndroidEntryPoint
class ListFragment : Fragment() {
private var pendingIntent: PendingIntent? = null
private var alarmManager: AlarmManager? = null
private val calendar = Calendar.getInstance()
private var _binding: FragmentListBinding? = null
private val binding get() = _binding!!
private val viewModel: DictionaryViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentListBinding.inflate(inflater, container, false)
val view = binding.root
createNotificationChannel()
setAlarm()
// viewModel.getRandomWordForNotification()
return view
}
override fun onDestroyView() {
_binding = null
super.onDestroyView()
}
private fun createNotificationChannel(){
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O){
val name: CharSequence = "ReminderChannel"
val description = "Channel For Alarm Manager"
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel("channelID", name, importance)
channel.description = description
val notificationManager = context?.getSystemService(NotificationManager::class.java)
notificationManager?.createNotificationChannel(channel)
}
}
private fun setAlarm(){
alarmManager = context?.getSystemService(ALARM_SERVICE) as AlarmManager
val intent = Intent(context, AlarmReceiver::class.java)
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0)
calendar[Calendar.HOUR_OF_DAY] = HOUR_FOR_NOTIFICATION
calendar[Calendar.MINUTE] = 0
calendar[Calendar.SECOND] = 0
calendar[Calendar.MILLISECOND] = 0
alarmManager!!.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
}
}
BroadcastReceiver for notification
class AlarmReceiver(): BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val i = Intent(context, ListFragment::class.java)
intent!!.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK // ?
val pendingIntent = PendingIntent.getActivity(context, 0, i, 0)
val notification = NotificationCompat.Builder(context!!, "channelID")
.setSmallIcon(R.drawable.ic_add_notification)
.setContentTitle("Daily Reminder")
.setContentText("Word - Translation")
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.build()
val notificationManager = NotificationManagerCompat.from(context)
notificationManager.notify(123, notification)
}
}
It's important to note that your viewModel
and the method getRandomWordForNotification()
will be called while your view is active. In your case that does not help you with getting a random word while your app is in the background/killed.
You should modify your AlarmReceiver
to start a Service
where you will call your repository, get your new random word and construct your notification.
class AlarmReceiver(): BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val service = Intent(context, MyRandomWordService::class.java)
ContextCompat.startForegroundService(context, serviceIntent);
}
}
class MyRandomWordService(name: String = "MyRandomWordService"): IntentService(name) {
override fun onHandleIntent(intent: Intent?) {
val notification = NotificationCompat.Builder(this.applicationContext, "channelID")
.setSmallIcon(R.drawable.ic_add_notification)
.setContentTitle("Daily Reminder")
.setContentText(getRandomWordForNotification())
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.build()
val notificationManager = NotificationManagerCompat.from(context)
notificationManager.notify(123, notification)
}
fun getRandomWordForNotification(): String {
// your code for getting the words
}
}
In addition to this, register the service in your AndroidManifest file.
<application ...>
<service android:name=".MyRandomWordService"
</service>
</application>
A few disclaimers:
IntentService was deprecated in API level 30.
AlarmManager is often replaced with WorkManager: https://developer.android.com/reference/androidx/work/WorkManager and https://developer.android.com/topic/libraries/architecture/workmanager