Schedule Android function when App is closed at specific time - android

I want to create an App that throws a notification everyday at 20pm. For that I need to time a function that gets executed every day at 20pm. Whats the best way to solve this? What should I use?
This is the function I want to execute:
private fun throwNotification() {
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val intent = Intent(applicationContext, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
notificationChannel = NotificationChannel(channelId, description, NotificationManager.IMPORTANCE_HIGH)
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.RED
notificationChannel.enableVibration(true)
notificationManager.createNotificationChannel(notificationChannel)
builder = Notification.Builder(this, channelId)
.setContentTitle("Test")
.setContentText("This is a test notification")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setChannelId(channelId)
notificationManager.notify(0, builder.build())
}

You should be concerned following tasks.
The function should be executed at exactly 20pm.
#1 should be repeated everyday.
The notification should be pushed even if the app is closed.
Above issues should not matter whether the device restarts.
The solution I found is following and that requires the app should be launched at least once.
#1~3 can be implemented by AlarmManager.
At app's first launch, call following code that registers alarmIntent.
private var alarmMgr: AlarmManager? = null
private lateinit var alarmIntent: PendingIntent
alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(context, YourAlarmReceiver::class.java).let { intent ->
PendingIntent.getBroadcast(context, 0, intent, 0)
}
// Set the alarm to start at 20:00.
val calendar: Calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis()
set(Calendar.HOUR_OF_DAY, 20)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
}
// setRepeating() lets you specify a precise custom interval--in this case,
// 1 day.
alarmMgr?.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
1000 * 60 * 60 * 24,
alarmIntent
)
Here, YourAlarmReceiver's onReceive() will be called at every 20pm by alarmIntent.
So what you have to do is only calling throwNotification() inside this onReceive().
#4 is also easy, that being said, it can be implemented by listening to BOOT_COMPLETED event.

Related

How to update Activity UI from broadcast receiver without creating sub class of receiver inside the activity in Android Kotlin?

I am receiving broadcast from another app in frequent interval. When I first receive the broadcast it shows the message data received from the broadcast by opening the activity. But after the activity is opened and I receive another broadcast, it is not updating that value in the Activity.
I don't want to create the subclass of receiver in my activity class because I want to register the receiver on manifest file.
This is my receiver code.
val activity = Intent(context, DisplayUpdate::class.java)
activity.putExtra("Key", intent.extras!!.getString("Key"))
activity.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(activity)
This is my isplayUpdate Activity code.
val bundle = intent.extras!!.getString("Key")
binding.textview.text = bundle
when (bundle!!.toInt()) {
200 -> {
Log.d("notiapp", "onCreate: when 200")
binding.textview.text = "Downloading"
}
300 -> {
Log.d("notiapp", "onCreate: when 300")
binding.textview.text = "Verifying"
}
400 -> {
Log.d("notiapp", "onCreate: when 400")
binding.textview.text = "Installing"
}
else ->
binding.textview.text = "No Updates"
}
Another way in which I am doing this is to show the notification when I receive the broadcast. When I click on notification it opens the activity with the message received from the broadcast. But here also I am getting the same issue which is when I click on first notification it opens the activity but after clicking on second or third notification it doesn't reopen the activity or change the value of the message in the activity.
This implementation in below.
val intent1 = Intent(context, DisplayUpdate::class.java)
intent1.putExtra("Key", intent?.extras!!.getString("Key").toString())
intent1.flags = Intent.FLAG_ACTIVITY_NEW_TASK
if (intent?.extras!!.getString("Key").toString() == "200") {
// Prepare a notification with vibration, sound and lights
val builder = NotificationCompat.Builder(context)
.setAutoCancel(true)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle("Downloading")
.setContentText("notificationText")
.setLights(Color.RED, 1000, 1000)
.setVibrate(longArrayOf(0, 400, 250, 400))
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(
PendingIntent.getActivity(
context,
0,
intent1,
PendingIntent.FLAG_UPDATE_CURRENT
)
)
// Automatically configure a Notification Channel for devices running Android O+
Pushy.setNotificationChannel(builder, context)
// Get an instance of the NotificationManager service
val notificationManager =
context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
// Build the notification and display it
notificationManager.notify(1, builder.build())
} else if (intent?.extras!!.getString("Key").toString() == "300") {
// Prepare a notification with vibration, sound and lights
val builder = NotificationCompat.Builder(context)
.setAutoCancel(true)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle("Downloaded")
.setContentText("notificationText")
.setLights(Color.RED, 1000, 1000)
.setVibrate(longArrayOf(0, 400, 250, 400))
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(
PendingIntent.getActivity(
context,
0,
intent1,
PendingIntent.FLAG_UPDATE_CURRENT
)
)
// Automatically configure a Notification Channel for devices running Android O+
Pushy.setNotificationChannel(builder, context)
// Get an instance of the NotificationManager service
val notificationManager =
context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
// Build the notification and display it
notificationManager.notify(1, builder.build())
} else if (intent?.extras!!.getString("Key").toString() == "400") {
// Prepare a notification with vibration, sound and lights
val builder = NotificationCompat.Builder(context)
.setAutoCancel(true)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle("Verifying")
.setContentText("notificationText")
.setLights(Color.RED, 1000, 1000)
.setVibrate(longArrayOf(0, 400, 250, 400))
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(
PendingIntent.getActivity(
context,
0,
intent1,
PendingIntent.FLAG_UPDATE_CURRENT
)
)
// Automatically configure a Notification Channel for devices running Android O+
Pushy.setNotificationChannel(builder, context)
// Get an instance of the NotificationManager service
val notificationManager =
context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
// Build the notification and display it
notificationManager.notify(1, builder.build())
}
Do I need to provide any more details ?
Thanks.

SetAlarmClock not showing alarm in notification

According to the docs:
The expectation is that when this alarm triggers, the application will
further wake up the device to tell the user about the alarm -- turning
on the screen, playing a sound, vibrating, etc. As such, the system
will typically also use the information supplied here to tell the user
about this upcoming alarm if appropriate.
SetAlarmClock docs
Is this done automatically? or I have to add a service with a notification.
I have read about setAlarmClock including a visible notification, or has the default behaviour been changed?
val activityIntent = Intent(requireContext(), AlarmClickedActivity::class.java)
pendingIntent =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.getActivity(
requireContext(),
0,
activityIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
} else {
PendingIntent.getActivity(
requireContext(),
0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT
)
}
val alarmClockInfo = AlarmManager.AlarmClockInfo(alarm.timeInMilliSecond, null)
alarmManager.setAlarmClock(alarmClockInfo, pendingIntent)
This only opens a new activity (AlarmClickedActivity) when the alarm goes off.
I don't get the notification of 'Current Alarm' or 'Upcoming Alarm' as mentioned in the docs
Firstly go to your app setting and give notification permission then run again and set a alarm then check.
If still having problem then use my code
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
Log.d("this", "notify")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val intent = Intent(context, AlarmActivity2::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
val pendingIntent = PendingIntent.getActivity(context, 0, intent, 0)
val builder = NotificationCompat.Builder(context, "111")
.setSmallIcon(R.drawable.blue_stringart)
.setContentTitle("Alarm is running")
.setAutoCancel(true)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setDefaults(NotificationCompat.DEFAULT_SOUND)
.setDefaults(NotificationCompat.DEFAULT_VIBRATE)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.addAction(R.drawable.ic_baseline_stop_24,"Stop",pendingIntent)
.setContentIntent(pendingIntent)
val notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
val r = RingtoneManager.getRingtone(context, notification)
r.play()
val notificationManagerCompat = NotificationManagerCompat.from(context)
notificationManagerCompat.notify(123, builder.build())
}
}
}
Then go to activity class and set your alarm in a method.
private fun setAlarm1() {
var calender: Calendar
calender = Calendar.getInstance()
calender.set(Calendar.HOUR_OF_DAY, PUT_YOUR_ALARM HOUR)
calender.set(Calendar.MINUTE, PUT_YOUR_ALARM MINUTE)
calender.set(Calendar.SECOND, 0)
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val thuReq: Long = Calendar.getInstance().timeInMillis + 1
var reqReqCode = thuReq.toInt()
if (calender.timeInMillis < System.currentTimeMillis()) {
calender.add(Calendar.DAY_OF_YEAR, 1)
}
val alarmTimeMilsec = calender.timeInMillis
val intent = Intent(this, AlarmReceiver::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
val pendingIntent = PendingIntent.getBroadcast(this, reqReqCode, intent, 0)
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calender.timeInMillis,
24 * 60 * 60 * 1000,
pendingIntent
)
Note -
1.alarmManager.setRepeating here you can use your alarm type as your wish.
2.requestcode must be unique for each alarm.
3. you must take a alarm time and keep in calender.timeInMillis which is you expecting alarm time.
still problem comments below

Android: Self managed ConnectionService, how to implement actions in custom incoming call screen

I am building a Voip app in android. Everything is working fine but I am not able to figure out how to accept and reject calls.
I use TelephoneManager#addNewIncomingCall to report new calls to the system. After that, I created a Connection object in ConnectionService#onCreateIncomingConnection and returned it. The onShowIncomingCallUi gets called and I create a notification this way:
val intent = Intent(context, TokboxActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
this.putExtras(this#Call.extras)
}
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val notification = NotificationCompat.Builder(context, "OKDOK")
.setSmallIcon(R.drawable.common_full_open_on_phone)
.setContentTitle("OKDOK")
.setContentText("Incoming call from ${extras.getString("docName")}")
.setPriority(NotificationCompat.PRIORITY_MAX)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setFullScreenIntent(pendingIntent, true)
.build()
notification.flags = notification.flags or NotificationCompat.FLAG_INSISTENT
val notificationManager = context.getSystemService(
NotificationManager::class.java)
notificationManager.notify("OKDOK", 0, notification)
I am getting the notification too. But I have two buttons in TokboxActivity. I want them to accept and reject the call. How do I implement that?

Open activity after click in notification in alarmmanager and broadcast Kotlin

I set on my application the notification every 7 hours in this way:
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(this, AlarmBroadcastReceiver::class.java)
pendingIntent = PendingIntent.getBroadcast(this, REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
// Setting the specific time for the alarm manager to trigger the intent, in this example, the alarm is set to go off at 23:30, update the time according to your need
val calendar = Calendar.getInstance()
val next= calendar.get(Calendar.HOUR_OF_DAY) + 7
calendar.timeInMillis = System.currentTimeMillis()
calendar.set(Calendar.HOUR_OF_DAY, next)
calendar.set(Calendar.MINUTE, 0)
calendar.set(Calendar.SECOND, 0)
// Starts the alarm manager
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
with this class AlarmBroadcastReceiver :
class AlarmBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create the NotificationChannel
val name = "Alarme"
val descriptionText = "Detalhes do Alarme"
val importance = NotificationManager.IMPORTANCE_DEFAULT
val mChannel = NotificationChannel("AlarmId", name, importance)
mChannel.description = descriptionText
val notificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(mChannel)
}
// Create the notification to be shown
val mBuilder = NotificationCompat.Builder(context!!, "AlarmId")
.setSmallIcon(R.mipmap.ic_food)
.setContentTitle("Synchronize Fitbit")
.setContentText("Synchronize Fitbit data and log-in SugarFree for don't lose daily data")
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Get the Notification manager service
val am = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Generate an Id for each notification
val id = System.currentTimeMillis() / 1000
// Show a notification
am.notify(id.toInt(), mBuilder.build())
The notifications working well, I enter in the application, set the alarm and after 7 hours arrive the notification and so on. I wish that when arrive the notification i can click on it and open the app (maybe in my current home activity) so this alarm wish set automatically after 7 hours.
I saw that I must modify the pendingIntent with my home intent... but I have a
val intent = Intent(this, AlarmBroadcastReceiver::class.java)
that need to call the Alarm Receiver class.
Can anyone help me out?
All you need is to add .setContentIntent in your notification builder.
// Create the notification to be shown
val mBuilder = NotificationCompat.Builder(context!!, "AlarmId")
.setSmallIcon(R.mipmap.ic_food)
.setContentTitle("Synchronize Fitbit")
.setContentText("Synchronize Fitbit data and log-in SugarFree for don't lose daily data")
.setAutoCancel(true)
.setContentIntent(PendingIntent.getActivity(
context, // Context from onReceive method.
0,
Intent(context, HomeActivity::class.java), // Activity you want to launch onClick.
0
)
)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.build()
You can find out more here the docs have more information about how to handle tasks such as only single Activity opens at a time.
You need create and set pending intent -
// Create an Intent for the activity you want to start
val resultIntent = Intent(this, YourMainActivity::class.java)
// Create the TaskStackBuilder
val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(this).run {
// Add the intent, which inflates the back stack
addNextIntentWithParentStack(resultIntent)
// Get the PendingIntent containing the entire back stack
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
}
and then set it -
val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
setContentIntent(resultPendingIntent)
...
}
with(NotificationManagerCompat.from(this)) {
notify(NOTIFICATION_ID, builder.build())
}
Hope this will work for you.

How to remove the notification after the particular time in android?

I am creating an simple android application in that created a notification.
Now i want to remove the notification if the user doesn't response after the particular time
That means i want remove the notification after five mins
The current correct solution may be to use:
NotificationCompat.Builder#setTimeoutAfter(long)
What you need is a combination of Alarmmanager and notificationmanger.
Register the alarm manager that will call a service in 5 minutes and use NotificationManager.cancel in the service implementation.
Alarm Service Sample is here. I suppose you know to use Notification Manager.
AlarmManager is more often used for complicated Services that have to run in the Background when the Application is closed.
You could also use a classic Java Runnable in a Handler for a simple small Thread.
Handler h = new Handler();
long delayInMilliseconds = 5000;
h.postDelayed(new Runnable() {
public void run() {
mNotificationManager.cancel(id);
}
}, delayInMilliseconds);
Also look here:
Clearing notification after a few seconds
You could also use the TimerTask-Class.
For Android >= 8.0 (Oreo) we can use this,
NotificationCompat.Builder#setTimeoutAfter(long)
For Android < 8.0 we can use AlarmManager
Add this to AndroidManifest.xml :
<receiver
android:name=".AutoDismissNotification"/>
Create AutoDismissNotification.kt and add this code :
class AutoDismissNotification : BroadcastReceiver() {
companion object {
private const val KEY_EXTRA_NOTIFICATION_ID = "notification_id"
}
override fun onReceive(context: Context, intent: Intent) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancel(intent.getIntExtra(KEY_EXTRA_NOTIFICATION_ID, 0))
}
fun setAlarm(context: Context, notificationId: Int, time: Long) {
val alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val alarmIntent = Intent(context, AutoDismissNotification::class.java)
alarmIntent.putExtra(KEY_EXTRA_NOTIFICATION_ID, notificationId)
val alarmPendingIntent = PendingIntent.getBroadcast(context, notificationId, alarmIntent, PendingIntent.FLAG_ONE_SHOT)
alarmMgr.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + time, alarmPendingIntent)
}
fun cancelAlarm(context: Context, notificationId: Int) {
val alarmIntent = Intent(context, AutoDismissNotification::class.java)
alarmIntent.putExtra(KEY_EXTRA_NOTIFICATION_ID, notificationId)
val alarmPendingIntent = PendingIntent.getBroadcast(context, notificationId, alarmIntent, PendingIntent.FLAG_ONE_SHOT)
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.cancel(alarmPendingIntent)
}
}
When you build the notification, add this :
long timeOut = 5 * 1000L; // Five seconds
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setTimeoutAfter(timeOut);
}
else {
AutoDismissNotification().setAlarm(this, notificationId, timeOut);
}
You can create your notification like this.
NotificationCompat.Builder notification = new NotificationCompat.Builder(context)
.setSmallIcon(Util.getNotificationIcon(context))
.setContentTitle(new SessionManager().getDomainPreference(context))
.setAutoCancel(true)
.setOngoing(false)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setShowWhen(false)
.setContentText(summaryText)
.setTimeoutAfter(3000) // add time in milliseconds
.setChannelId(CHANNEL_ID);

Categories

Resources