I have developed a reminder app using kotlin. You can set title, memo and date and time and it's going to show notification to the user on exact set of date and time. The problem is that on that time nothing happens though everything seems totally fine. I'll provide you with my codes and I hope you'll help me to fix it. Thanks in advance.
Here's my Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.XReminder"
tools:targetApi="31">
<activity
android:name=".activity.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".notification.NotificationReceiver" />
</application>
</manifest>
Notification Class:
@RequiresApi(Build.VERSION_CODES.O)
class Notification(
name: String,
description: String,
private var context: Context,
var id: String,
private var reminder: Reminder
) {
init {
createChannel(name, description)
startNotification()
}
@SuppressLint("ScheduleExactAlarm")
private fun startNotification() {
val calendar = Calendar.getInstance()
calendar.set(Calendar.HOUR_OF_DAY, (reminder.time).split(":")[0].toInt())
calendar.set(Calendar.MINUTE, (reminder.time).split(":")[1].toInt())
calendar.set(Calendar.SECOND, 0) // Change its default from 13 to 0 to be precise
calendar.set(Calendar.MILLISECOND, 0) // Change its default from 14 to 0 to be precise
calendar.set(Calendar.DAY_OF_YEAR, (reminder.date).split(".")[0].toInt())
calendar.set(
Calendar.MONTH,
(reminder.date).split(".")[1].toInt() - 1
) // Month start from 0 but in reality it starts from 1
calendar.set(Calendar.YEAR, (reminder.date).split(".")[2].toInt())
val notificationIntent = Intent(context, NotificationReceiver::class.java)
notificationIntent.putExtra("id", id)
val alarmManager = context.getSystemService(ALARM_SERVICE) as AlarmManager
alarmManager.setExact(
AlarmManager.RTC_WAKEUP, calendar.timeInMillis, PendingIntent.getBroadcast(
context, id.toInt(), notificationIntent, PendingIntent.FLAG_IMMUTABLE
)
)
}
@RequiresApi(Build.VERSION_CODES.O)
private fun createChannel(name: String, description: String) {
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(id, name, importance)
channel.description = description
val notificationManager = context.getSystemService(NotificationManager::class.java)
notificationManager.createNotificationChannel(channel)
}
}
NotificationReceiver Class:
class NotificationReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val currentId = intent!!.extras!!.getString("id")
val notificationManager =
context!!.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Use runBlocking because we have no access to lifecycleScope
runBlocking {
val currentReminder = context.dataStore.data.first().remindersList.find {
it.hashCode() == currentId!!.toInt()
}
createNotification(
context,
currentId.toString(),
currentReminder!!.title,
currentReminder.memo,
notificationManager
)
}
}
private fun createNotification(
context: Context?,
id: String,
title: String,
memo: String,
notificationManager: NotificationManager
) {
val notification = NotificationCompat.Builder(context!!, id)
.setSmallIcon(R.drawable.baseline_notification_important)
.setContentTitle(title)
.setContentText(memo)
.setPriority(NotificationCompat.PRIORITY_HIGH).build()
notificationManager.notify(id.toInt(), notification)
}
}
I tried to debug the app. I put breakpoints almost everywhere and I realized all data have been passed correctly.
SOLUTION
As it runs on android 13, notification is blocked as default and we have to implement runtime permission in MainActivity.