I am new to android studio. I was trying to create a notification when user click on a button embedded in recyclerView
user has to give time in Hours and Minutes only. I take user input as a string. And input is stored in SQLite database.
notifyMeUpdate function is working fine but Toast in Receiver class is not shown(I think Receiver class is not triggered).
Please ignore typo
Here is my code:
class User{
var id = 0
var time = ""
var amp = ""
var text = ""
var notifyMe = false
}
My User Class:
fun notifyMeUpdate(user: User) {
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
var hour = 0
var min = 0
for(i in 0 until user.time.length) {
if (user.time[i] == ':'){
var str = user.time.subSequence(0, i).toString()
var minStr = user.time.subSequence(i+1, user.time.length).toString()
if(user.amp == "AM"){
hour = str.toInt()
min = minStr.toInt()
}
else{
hour = str.toInt() + 12
min = minStr.toInt()
}
}
}
val cur_cal: Calendar = GregorianCalendar()
cur_cal.timeInMillis = System.currentTimeMillis()
val cal: Calendar = GregorianCalendar()
cal.add(Calendar.DAY_OF_YEAR, cur_cal[Calendar.DAY_OF_YEAR])
cal[Calendar.HOUR_OF_DAY] = hour
cal[Calendar.MINUTE] = min
cal[Calendar.SECOND] = 0
cal[Calendar.MILLISECOND] = cur_cal[Calendar.MILLISECOND]
cal[Calendar.DATE] = cur_cal[Calendar.DATE]
cal[Calendar.MONTH] = cur_cal[Calendar.MONTH]
val intent = Intent(context, Receiever::class.java)
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.timeInMillis, pendingIntent)
}
And here is my Receiever class
class Receiever: BroadcastReceiver(){
lateinit var notificationManager: NotificationManager
lateinit var notificationChannel: NotificationChannel
lateinit var builder: Notification.Builder
private var channelId = "package com.example.recyclerpractise"
private var description = "Text Notification"
override fun onReceive(context: Context?, intent: Intent?){
Toast.makeText(context, "Triggred", Toast.LENGTH_SHORT).show()
val intent = Intent(context, LauncherActivity::class.java)
val pintent = PendingIntent.getActivity(context, 0 , intent, PendingIntent.FLAG_UPDATE_CURRENT)
if (context != null) {
notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationChannel =
NotificationChannel(channelId, description, NotificationManager.IMPORTANCE_HIGH)
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.GREEN
notificationChannel.enableVibration(true)
notificationManager.createNotificationChannel(notificationChannel)
if (context != null) {
builder = Notification.Builder(context, channelId)
.setContentTitle("Hello Moto")
.setContentText("Test Notification")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setLargeIcon(BitmapFactory.decodeResource(context.resources, R.drawable.ic_launcher_foreground))
.setContentIntent(pintent)
}
else{
builder = Notification.Builder(context)
.setContentTitle("Hello Moto")
.setContentText("Test Notification")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setLargeIcon(BitmapFactory.decodeResource(context?.resources, R.drawable.ic_launcher_foreground))
.setContentIntent(pintent)
}
notificationManager.notify(19867, builder.build())
}
}
}
Here is my onBindViewHolder of recycler list
override fun onBindViewHolder(p0: ViewHolder, p1: Int) {
val user: User = userList[p1]
p0.time.text = user.time
p0.text.text = user.text
p0.img.setOnClickListener{
val popup = PopupMenu(activity, p0.img)
popup.inflate(R.menu.schedulemenu)
popup.setOnMenuItemClickListener {
when(it.itemId){
R.id.menu_delete->{
activity.dbHelper.deleteData(userList[p1].id.toLong())
activity.refreshList()
}
R.id.menu_update->{
activity.updateUser(userList[p1])
}
R.id.notify->{
activity.notifyMeUpdate(userList[p1])
}
}
true
}
popup.show()
}
}
Thanks for Help
Thanks for all who tried. After several hours of debugging. I found that I did a very stupid mistake that haven't register my receiver in manifest file now it's working fine.
Related
i have a problem with chronometer in Notification. I want to get current tick if notification clicked and parsing value to MainActivity using Intent. i have no idea about this case, i was try and result is always 0.
here my notification code with RemoteView
fun showNotification(context: Context, value: Long, state: Int) {
val isPaused = state == Constant.MusicState.PAUSED
val intentTimer = Intent(context, MainActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val bundle = Bundle()
bundle.putLong(Constant.Key.CURRENT_TIME, value)
val pendingIntentButtonPause = PendingIntent.getActivity(context, 100, intentTimer, PendingIntent.FLAG_UPDATE_CURRENT, bundle)
val remoteViews = RemoteViews(context.packageName, R.layout.item_notification)
remoteViews.setChronometer(R.id.chronometer, value, null, !isPaused)
remoteViews.setOnClickPendingIntent(R.id.buttonPause, pendingIntentButtonPause)
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val builder = NotificationCompat.Builder(context, "199102")
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentText("Test")
.setAutoCancel(false)
.setOngoing(true)
.setOnlyAlertOnce(true)
.setUsesChronometer(true)
.setContentIntent(PendingIntent.getActivity(context, 10, intentTimer, PendingIntent.FLAG_UPDATE_CURRENT))
remoteViews
builder.setCustomContentView(remoteViews)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
checkNotificationChannel(context, "199102")
}
notificationManager.notify(199102, builder.build())
}
And this when i call function showNotification()
this.binding.apply {
this#MainActivity.musicState = Constant.MusicState.IDLE
this.chronometer.setOnChronometerTickListener {
try {
if (it.text == "00.10" || it.text == "00:10") {
Chronotification.showNotification(this#MainActivity, it.base, this#MainActivity.musicState)
this#MainActivity.musicState = Constant.MusicState.IDLE
this#MainActivity.binding.buttonStart.text = "Start"
it.text = "00.00"
it.stop()
}
}catch (e : Exception) {
e.printStackTrace()
}
}
GeneralHelper.makeClickable(this#MainActivity, this.buttonStart)
}
Thanks, any help or suggestion will be appreciate.
I already made a notification without intent to MainActivity and it works fine, but when I add that intent to my MainActivity the notification does not show anymore. Is there anything wrong with my code or do I need to change the manifest or add some code in my MainActivity?
Here is my code. I set it into two functions - setDailyReminder and showAlarmNotification.
fun setDailyReminder(context: Context, type: String, message: String) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, MainActivity::class.java)
intent.putExtra(EXTRA_MESSAGE, message)
intent.putExtra(EXTRA_TYPE, type)
val timeArray =
TIME_DAILY.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val calendar = Calendar.getInstance()
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeArray[0]))
calendar.set(Calendar.MINUTE, Integer.parseInt(timeArray[1]))
calendar.set(Calendar.SECOND, 0)
val pendingIntent = PendingIntent.getBroadcast(context,
ID_DAILY, intent, 0)
alarmManager.setInexactRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
Toast.makeText(context, "Daily reminder set up", Toast.LENGTH_SHORT).show()
}
private fun showAlarmNotification(
context: Context,
title: String,
message: String?,
notifId: Int
) {
val CHANNEL_ID = "Github App"
val CHANNEL_NAME = "Let's find favourite user on Github"
val notificationManagerCompat =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp)
.setContentTitle(title)
.setContentText(message)
.setSound(alarmSound)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT
)
builder.setChannelId(CHANNEL_ID)
notificationManagerCompat.createNotificationChannel(channel)
}
val notification = builder.build()
notification.flags = notification.flags or Notification.FLAG_AUTO_CANCEL
notificationManagerCompat.notify(notifId, notification)
}
fun showNotification(context: Context,title: String, message:String, notifId: Int){
createNotificationChannel(context)
val intent = Intent(context, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this, 0,
intent,PendingIntent.FLAG_ONE_SHOT)
var builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setColor(resources.getColor(R.color.colorAccent))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
val notificationManagerCompat = NotificationManagerCompat.from(this)
notificationManagerCompat.notify(notifId, builder.build())
}
private fun createNotificationChannel(context: Context) {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = "Test"
val descriptionText = "FCM"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
}
// Register the channel with the system
val notificationManager: NotificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
I'm making an app that i schedule notifications for a day say morning , evening and night - the problem is if i opened the app at night the old notifications of morning and evening shows . i use below code
val alarmMgr = MyApplication.appContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager?
val intent = Intent(MyApplication.appContext, MyAlarmReceiver::class.java)
intent.putExtra("Title",title)
intent.putExtra("Body",body)
intent.putExtra("Id",id)
intent.putExtra("Sound",sound)
val pendingIntent = PendingIntent.getBroadcast(MyApplication.appContext, id, intent, 0)
alarmMgr!!.setRepeating(AlarmManager.RTC_WAKEUP,time,AlarmManager.INTERVAL_DAY,pendingIntent)
With this part inside onReceive of alarm
private fun sendNotification( intent: Intent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationID = intent.extras!!.getInt("Id")!!
val title = intent.extras!!.getString("Title")
val body = intent.extras!!.getString("Body")
val sound = intent.extras!!.getString("Sound")
val channelID = "com.ebookfrenzy.notifydemo.news"
val resultIntent = Intent(MyApplication.appContext, MainActivity::class.java)
resultIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(
MyApplication.appContext,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT)
val notification = Notification.Builder(MyApplication.appContext,
channelID)
.setContentTitle(title)
.setContentText(body)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setChannelId(channelID)
.setContentIntent(pendingIntent)
.build()
sound?.let {
notification.sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + MyApplication.appContext.getPackageName() + "/raw/$it")
}
var notificationManager = MyApplication.appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager?.notify(notificationID, notification)
} else {
}
}
I have tried using "0" notification id and as well as unique notification id.
Also used setGroup() like below. It still generates a new notification every time. I want to merge the notification body and set the title as common.
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
remoteMessage?.let {
sendNotification(it.data["alert"])
}
}
private fun sendNotification(messageBody: String?) {
val channelId = "${this.packageName}-${this.getString(R.string.app_name)}"
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val builder = NotificationCompat.Builder(this, channelId).apply {
setDefaults(Notification.DEFAULT_ALL)
setSmallIcon(if (Build.VERSION.SDK_INT >= 21) R.mipmap.ic_launcher else R.mipmap.ic_launcher_round)
setContentTitle(getString(R.string.app_name))
setContentText(messageBody)
setDefaults(NotificationCompat.DEFAULT_SOUND or NotificationCompat.DEFAULT_VIBRATE or NotificationCompat.DEFAULT_LIGHTS)
setStyle(NotificationCompat.BigTextStyle().bigText(messageBody))
priority = NotificationCompat.PRIORITY_DEFAULT
setAutoCancel(true)
setSound(defaultSoundUri)
setGroup(getString(R.string.app_name))
setGroupSummary(true)
}
val manager = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId, getString(R.string.default_channel_name), NotificationManager.IMPORTANCE_HIGH)
manager?.createNotificationChannel(channel)
}
val intent = Intent(this, DashboardFlowActivity::class.java)
intent.putExtra(DashboardFlowActivity.ISFROMNOTIFICATION, true)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
builder.setContentIntent(pendingIntent)
//manager?.cancelAll()
manager?.notify(this.getString(R.string.app_name), getID(), builder.build())
}
}
private val c = AtomicInteger(0)
private fun getID(): Int {
return c.incrementAndGet()
}
Anything I am doing wrong here? Also, I have gone through this answer. setgroup() in notification not working
Finally I got solution for this question using https://stackoverflow.com/a/41114135/6021469, https://www.developer.com/ws/android/creating-bundled-notifications-with-android.html
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
remoteMessage?.let {
sendNotification(it.data["alert"])
}
}
private fun sendNotification(messageBody: String?) {
val channelId = "${this.packageName}-${this.getString(R.string.app_name)}"
val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val builder = NotificationCompat.Builder(this, channelId).apply {
setDefaults(Notification.DEFAULT_ALL)
setSmallIcon(if (Build.VERSION.SDK_INT >= 21) R.mipmap.ic_launcher else R.mipmap.ic_launcher_round)
setContentTitle(getString(R.string.app_name))
setShowWhen(true)
setContentText(messageBody)
setDefaults(NotificationCompat.DEFAULT_SOUND or NotificationCompat.DEFAULT_VIBRATE or NotificationCompat.DEFAULT_LIGHTS)
setStyle(NotificationCompat.BigTextStyle().bigText(messageBody))
priority = NotificationCompat.PRIORITY_DEFAULT
setAutoCancel(true)
setShowWhen(true)
setSound(defaultSoundUri)
setGroup(getString(R.string.app_name))
}
val builderSummary = NotificationCompat.Builder(this, channelId).apply {
setDefaults(Notification.DEFAULT_ALL)
setSmallIcon(if (Build.VERSION.SDK_INT >= 21) R.mipmap.ic_launcher else R.mipmap.ic_launcher_round)
setContentTitle(getString(R.string.app_name))
setShowWhen(true)
setContentText(messageBody)
setDefaults(NotificationCompat.DEFAULT_SOUND or NotificationCompat.DEFAULT_VIBRATE or NotificationCompat.DEFAULT_LIGHTS)
setStyle(NotificationCompat.BigTextStyle().bigText(messageBody))
priority = NotificationCompat.PRIORITY_DEFAULT
setAutoCancel(true)
setShowWhen(true)
setSound(defaultSoundUri)
setGroup(getString(R.string.app_name))
setGroupSummary(true)
}
val manager = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId, getString(R.string.default_channel_name), NotificationManager.IMPORTANCE_HIGH)
manager?.createNotificationChannel(channel)
}
val intent = Intent(this, DashboardFlowActivity::class.java)
intent.putExtra(DashboardFlowActivity.ISFROMNOTIFICATION, true)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
builder.setContentIntent(pendingIntent)
manager?.notify(this.getString(R.string.app_name), getID(), builder.build())
manager?.notify(this.getString(R.string.app_name), 0, builderSummary.build())
}
}
private val c = AtomicInteger(0)
private fun getID(): Int {
return c.incrementAndGet()
}
I have a problem with notifications (NotificationManager class) in my android app. I made channel and notification. I read about the problem with 26 build and made a channel for notifications, but it doesn't solve my problem. But I have the next error in logcat.
E/NotificationService: No Channel found for pkg=com.gmail.mtswetkov.ocrraces,
channelId=com.google.MTsvetkov.CHANNEL_ID, id=103, tag=null,
opPkg=com.gmail.mtswetkov.ocrraces, callingUid=10087, userId=0,
incomingUserId=0, notificationUid=10087,
notification=Notification(channel=com.google.MTsvetkov.CHANNEL_ID
pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x0
color=0x00000000 vis=PRIVATE)
class NotificationsJobScheduler : JobService() {
private lateinit var mNotification: Notification
private lateinit var alarmIntent: PendingIntent
private lateinit var prefs: SharedPreferences
val gson = Gson()
private var notificationManager: NotificationManager? = null
lateinit var channel : NotificationChannel
private lateinit var notifList: MutableList<LocalNotification> //= mutableListOf(LocalNotification(0, Date(2017, 6, 11), "", ""))
companion object {
var started: Boolean = false
const val CHANNEL_ID = "com.google.MTsvetkov.CHANNEL_ID"
var notificationID = 101
const val CHANNEL_NAME = "Sample Notification"
const val CHANNEL_DISC = "Example News Channel"
}
override fun onStopJob(params: JobParameters?): Boolean {
return false
}
override fun onStartJob(params: JobParameters?): Boolean {
createNotificationChannel(
CHANNEL_ID,
CHANNEL_NAME,
CHANNEL_DISC)
sendNotification()
jobFinished(params, false)
return true
}
fun sendNotification() {
val intent = Intent(this, MainActivity::class.java)
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
alarmIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
//Get Notification list from SharedPreferences
prefs = this.getSharedPreferences(ShowSingleRaceActivity().PREFS_FILENAME, 0)
val jsonPerf: String = prefs.getString(ShowSingleRaceActivity().NOTIFICATION_OBJECTS, "")
if (jsonPerf != "") notifList = gson.fromJson(jsonPerf, object : TypeToken<MutableList<LocalNotification>>() {}.type)
//Check the date
val today = Calendar.getInstance()
for (notif in notifList) {
if (today.equals(notif.notifDate)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d("JSON", Build.VERSION.SDK_INT.toString())
mNotification = Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.yelbell)
.setContentTitle(notif.raceName)
.setContentText(notif.message)
.build()
notificationID++
} else {
mNotification = Notification.Builder(this)
.setSmallIcon(R.drawable.yelbell)
.setAutoCancel(true)
.setContentTitle(notif.raceName)
.setContentText(notif.message)
.build()
}
notificationManager?.notify(notificationID, mNotification)
}
}
}
private fun createNotificationChannel(id: String, name: String,
description: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val importance = NotificationManager.IMPORTANCE_LOW
channel = NotificationChannel(id, name, importance)
channel.description = description
channel.enableLights(true)
channel.lightColor = Color.RED
channel.enableVibration(true)
channel.vibrationPattern =
longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400)
notificationManager?.createNotificationChannel(channel)
}
}
}
it was necessary to move channel creation block into the cycle (where I created notification)
createNotificationChannel(CHANNEL_ID, CHANNEL_NAME,CHANNEL_DISC) --->
---->or (notif in notifList) {
if (today.equals(notif.notifDate)) {
**createNotificationChannel(CHANNEL_ID, CHANNEL_NAME,CHANNEL_DISC)**
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.d("JSON", Build.VERSION.SDK_INT.toString())
mNotification = Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.yelbell)
.setContentTitle(notif.raceName)
.setContentText(notif.message)
.build()
notificationID++
} else {
mNotification = Notification.Builder(this)
.setSmallIcon(R.drawable.yelbell)
.setAutoCancel(true)
.setContentTitle(notif.raceName)
.setContentText(notif.message)
.build()
}