Search code examples
androidkotlinbroadcastreceiverandroid-notificationsandroid-viewmodel

How to show different text in repeating notification Android


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)
    }
}

Solution

  • 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: