I tried to create an app that send a notification (with a customised text) when the time is the same the user inserted in the timePicker, but the notification doesn't appear at all.
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val UniqueID = 47245
timePicker.setIs24HourView(true)
button1.setOnClickListener {
if((Calendar.HOUR_OF_DAY == timePicker.hour) && (Calendar.MINUTE == timePicker.minute)) {
var notification = NotificationCompat.Builder(this, "M_CH_ID")
notification.setSmallIcon(R.mipmap.ic_launcher)
notification.setTicker(editText.text)
notification.setWhen(System.currentTimeMillis())
notification.setContentTitle("Notifica")
notification.setContentText(editText.text)
var ringtone: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
var intent = Intent(this, MainActivity::class.java)
var pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
notification.setContentIntent(pendingIntent)
notification.setLights(Color.RED, 2500, 1000)
notification.setSound(ringtone)
notification.setAutoCancel(true)
var notManager: NotificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
notManager.notify(UniqueID, notification.build())
}
}
}
Calendar.HOUR_OF_DAY and Calendar.MINUTE are constant values in the Calendar class to use with the get() method. To get the current hour and minute, you can do the following:
val now = Calendar.newInstance()
val hour = now.get(Calendar.HOUR_OF_DAY)
val minute = now.get(Calendar.MINUTE)
These are the values that your if check should be against.
Related
I think I have set my alarm manager to run at 7am then at 24 hour intervals after that. It should change a image view and then send a notification. Instead it sends a notification a minute or 2 after closing or opening the app and occasionally changes the image. Can someone please explain where I went wrong? or how I can fix this?
main activity -
val mIntent = Intent(this, MyReceiver::class.java)
val calendar: Calendar = Calendar.getInstance()
calendar.setTimeInMillis(System.currentTimeMillis())
calendar.set(Calendar.HOUR_OF_DAY, 7)
calendar.set(Calendar.MINUTE, 0)
val mPendingIntent = PendingIntent.getBroadcast(this, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val mAlarmManager = this
.getSystemService(Context.ALARM_SERVICE) as AlarmManager
mAlarmManager.setRepeating(
AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),86400000, mPendingIntent,
)
MyReciver -
class MyReceiver : BroadcastReceiver() {
#RequiresApi(Build.VERSION_CODES.O)
override fun onReceive(context: Context, intent: Intent) {
val titles = arrayOf("Become inspired!", "Check out this quote!", "A new quote appeared!", "Daily quote available!")
val title = titles.random()
val notificationChannel =
NotificationChannel("My Channel", "New Quote", NotificationManager.IMPORTANCE_DEFAULT).apply {
description = "Alerts when A new daily quote is set!"
}
val builder = NotificationCompat.Builder(context!!, "My Channel")
.setSmallIcon(R.drawable.ic_stat_name)
.setContentTitle(title)
.setContentText("A new daily quote is available for viewing")
with(NotificationManagerCompat.from(context)){
createNotificationChannel(notificationChannel)
notify(1, builder.build())
}
val quotes = arrayOf(R.drawable.i1, R.drawable.i2, R.drawable.i3, R.drawable.i5,
R.drawable.i6, R.drawable.i7, R.drawable.i8, R.drawable.i9, R.drawable.i10, R.drawable.i11, R.drawable.i12)
val quote = quotes.random()
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
with(prefs.edit()) {
putInt("paintings", quote)
apply()
}
}
}
Other -
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.other)
val imageView = findViewById<ImageView>(R.id.paininass)
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
val quote = prefs.getInt("paintings", R.drawable.i5)
imageView.setImageResource(quote)
Like CommonsWare says in the comments, using the current day and setting the time to 7AM is usually going to put that in the past, and as the AlarmManager#setRepeating docs say:
If the stated trigger time is in the past, the alarm will be triggered immediately, with an alarm count depending on how far in the past the trigger time is relative to the repeat interval.
So yeah, you need to add a day if it's in the past. You can do that by comparing currentTimeMillis to Calendar#getTimeInMillis, or using its before function, or however you want to do it. Then just call add(Calendar.DAY_OF_MONTH, 1)
I have 3 parts of code that are not working on my application, here they are:
Main activity -
class MainActivity : AppCompatActivity() {
var CHANNEL_ID = "myChannel"
private var mAlarmManager : AlarmManager? = null
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = getString(R.string.channel_name)
val descriptionText = getString(R.string.channel_description)
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
}
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val mIntent = Intent(this, MyReceiver::class.java)
val mPendingIntent = PendingIntent.getBroadcast(this, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val mAlarmManager = this
.getSystemService(Context.ALARM_SERVICE) as AlarmManager
mAlarmManager.setRepeating(
AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
60000, mPendingIntent
)
Qinperation -
class Qinperation : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.qinsperational)
val back18 = findViewById<Button>(R.id.back18)
back18.setOnClickListener {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
}
And MyReceiver -
class MyReceiver : BroadcastReceiver() {
var CHANNEL_ID = "myChannel"
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context,"This toast will be shown every X minutes", Toast.LENGTH_LONG).show()
Log.i("TAG","/////////////////// SHOW NOTIFICATION NOW //////////////////////")
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.orange)
.setLargeIcon(BitmapFactory.decodeResource(context.resources,R.mipmap.ic_launcher_round))
.setContentTitle("My notification")
.setContentText("Much longer text that cannot fit one line...")
.setStyle(
NotificationCompat.BigTextStyle()
.bigText("Much longer text that cannot fit one line...Much longer text that cannot fit one line..."))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
with(NotificationManagerCompat.from(context)) {
notify(12345, builder.build()) }
if (context !is Qinperation) return
val imageView = context.findViewById<View>(R.id.paininass) as ImageView
val quotes = arrayOf(R.drawable.i1, R.drawable.i2, R.drawable.i3, R.drawable.i5, R.drawable.i6, R.drawable.i7, R.drawable.i8, R.drawable.i9, R.drawable.i10, R.drawable.i11, R.drawable.i12)
val quote = quotes.random()
imageView.setImageResource(quote)
}
}
I want the receiver to run every set period (at the moment every minute), and then a notification to pop up and the image in the Qinperation activity to change to a randomized one. I know the receiver works due to the toast popping up successfully every minute. It then continues to say a notification cannot be posted to the notification channel "myChannel". After some research I concluded I needed to set up a channel that I thought I did in the main activity (using the android documentation), but it still doesn't work. It runs and just has that message pop up at the bottom. How would I successfully create this channel and run it so a notification pops up every set period of time?
As for the image view, I have the randomizer set up to run in the receiver and then based of the random image the image view to be set. It however stays blank throughout. Am I using the right command?
All help or tips are appreciated :)
I'm trying stopping running coroutineWorker from notification button. I tried 3 methods and 2 of them calls "Result.failure()" & working fine. However another one doesn't.
Below CoroutineWorker shows foregroundInfo and Starts ringtone.
class RingWork(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
companion object {
val ALARM_CHANNEL_ID = "alarm_channel6"
}
lateinit var ringtoneSound: Ringtone
val context = applicationContext
#RequiresApi(Build.VERSION_CODES.Q)
override suspend fun doWork(): Result {
return try {
val alarmId = inputData.getInt("alarmId", 0)
val notificationMgr =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
//CHANNEL
val alarmChannel = NotificationChannel(
ALARM_CHANNEL_ID, "alarm" ,NotificationManager.IMPORTANCE_HIGH
)
alarmChannel.setSound(null, null)
alarmChannel.enableVibration(false)
alarmChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
notificationMgr.createNotificationChannel(alarmChannel)
val fullScreenIntent = Intent(context, LockscreenActivity::class.java).putExtra("alarmId", alarmId)
//This calls "failure" properly
val fullScreenPendingIntent = PendingIntent.getActivity(context, 0, fullScreenIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
//This calls "failure" properly
val stop1PendingIntent =
WorkManager.getInstance(context).createCancelPendingIntent(getId())
val s2Intent = Intent(context, StopAlarmReceiver::class.java).putExtra("alarmId", alarmId)
//This is not.
val stop2PendingIntent = PendingIntent.getBroadcast(context, 1, s2Intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
val builder = NotificationCompat.Builder(context, ALARM_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_name)
.setContentTitle("title")
.setFullScreenIntent(fullScreenPendingIntent, true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_ALARM)
.setAutoCancel(true)
.setSound(null)
.setVibrate(null)
.addAction(R.drawable.ic_stat_name, "Stop1", stop1PendingIntent)
.addAction(R.drawable.ic_stat_name, "Stop2", stop2PendingIntent)
setForeground(
ForegroundInfo(1999999, builder.build(), FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK)
)
ringtoneSound =
RingtoneManager.getRingtone(context, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM))
ringtoneSound.play()
delay(30000L)
ringtoneSound.stop()
Result.success()
} catch (e: Exception) {
Result.failure()
} finally {
cleanup()
}
}
fun cleanup(){
ringtoneSound.stop()
}
}
In LockScreenActivity, there is a button to stop ringtone.
binding.stoppingbutton.setOnClickListener {
val workMgr = WorkManager.getInstance(applicationContext)
workMgr.cancelUniqueWork("RingWork-$alarmId")
finish()
}
This calls "result.failure" and "finally" then ringtone will stop, notification will disapear. working fine.
However, if I press "Stop2" button on the notification.
class StopAlarmReceiver: BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val alarmId = intent.getIntExtra("alarmId", 0)
val workMgr = WorkManager.getInstance(context)
workMgr.cancelUniqueWork("RingWork-$alarmId")
}
}
It cancels worker, but it won't call "result.failure" and "finally", so ringtone won't stop. Notification also won't disappear.
fullScreenPendingIntent and stop2PendingIntent are doing the same thing, but why it won't behave same?
You can edit your PendingIntent like this and it will trigger onReceive:
val stop2PendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
PendingIntent.getBroadcast(context, downloadFile.productId, cancelIntent, PendingIntent.FLAG_IMMUTABLE)
else
PendingIntent.getBroadcast(context, downloadFile.productId, cancelIntent, 0)
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.
I try to push notification by date to my app. I allready build the broadcast reciever and for some reason it didn't push the notification.
This is my code:
saveTime?.setOnClickListener() //save time notification
{
val hour: Int = tp!!.hour
val min: Int = tp!!.minute
var text = "" + hour + ":" + min
var calendar: Calendar = Calendar.getInstance()
calendar.set(Calendar.DAY_OF_WEEK,1)
calendar.set(Calendar.DAY_OF_WEEK,Calendar.FRIDAY)
calendar.set(Calendar.HOUR_OF_DAY,hour)
calendar.set(Calendar.MINUTE,min)
calendar.set(Calendar.SECOND, 0);
val intent = Intent()
val pendingIntent = PendingIntent.getActivity(this.activity,0,intent,PendingIntent.FLAG_UPDATE_CURRENT)
var alarmManager = this.activity.getSystemService(ALARM_SERVICE) as AlarmManager
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,calendar.timeInMillis, AlarmManager.INTERVAL_DAY,pendingIntent)
}
And here you'll see my broadcast reciever class:
class MyReciver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val timeAlert = System.currentTimeMillis()
val notificationManager = context
.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationIntent = Intent(context, MainActivity::class.java)
notificationIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
val pendingIntent = PendingIntent.getActivity(context, 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT)
//val alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val notification = Notification.Builder(context)
.setContentTitle("some title:")
.setContentText("some text")
.setSmallIcon(R.drawable.notification_icon_background)
.setAutoCancel(true).setWhen(timeAlert)
.setContentIntent(pendingIntent)
notificationManager.notify(0, notification.build())
}
}