How to remove the notification after the particular time in android? - 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);

Related

Alarm Pending intent returns null when app started again after killing from background

I am trying to check if a repeating alarm already exist. I am testing in MIUI 11 (OS v8.1) device, where i have set an alarm then removed the application from background. If i again opens the app a new alarm is created again
Here is my code to set a repeating alarm
private fun startAlarm() {
val CUSTOM_INTENT = "com.test.intent.action.ALARM"
val intent = Intent(this, AlarmHelper::class.java)
intent.action = CUSTOM_INTENT
val pendingIntent: PendingIntent =
getBroadcast(this, 101, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
System.currentTimeMillis()+60*60*1000, pendingIntent)
}
This checks if an alarm already exist then i will not create a new one.
private fun isAlarmExist() :Boolean =
PendingIntent.getBroadcast(this, 101,
Intent(this, AlarmHelper::class.java),
PendingIntent.FLAG_NO_CREATE) != null
Already tried this
private fun isAlarmExist() :Boolean =
PendingIntent.getBroadcast(this, 101,
Intent("com.example.dozemodepoc.MY_UNIQUE_ACTION"),
PendingIntent.FLAG_NO_CREATE) != null
// this didnot work either
Already gone through
How to check if AlarmManager already has an alarm set?
When force stopped the application and started the app again, new instance is again created. Any kind of help will be highly appreciated!!.
I did a silly mistake in my isAlarmExist()
private fun isAlarmExist() :Boolean {
val CUSTOM_INTENT = "com.test.intent.action.ALARM"
val intent = Intent(this#MainActivity, AlarmHelper::class.java)
intent.action = CUSTOM_INTENT
return getBroadcast(this#MainActivity, 101, intent, PendingIntent.FLAG_NO_CREATE)!=null
}
This pending intent should be exact of the pending intent which was created when alarm was set up.

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 Developing: notifications don't show when app is closed

How can I send scheduled notifications in Android Studio?
I got this task: I want to get notifications at the some chosen time of the day every day. I can easily get them when app is alive, but when its closed notifications don't come up.
I've already tried JobScheduler, AlarmManager and WorkManager and none of these didn't work well.
My project runs at minimum SDK 26 (Android Oreo). Target SDK is 30. Last code version looks like that:
AlertReceiver.java
public class AlertReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
intent = new Intent(context, NotificationService.class);
context.startService(intent);
}
}
NotificationService.java
public class NotificationService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
showNotifications();
return Service.START_STICKY;
}
private void showNotifications(){
NotificationHelper notificationHelper = new NotificationHelper(getApplicationContext());
NotificationCompat.Builder nb;
nb = notificationHelper.getChannelNotification("Title", "Description");
notificationHelper.getManager().notify(123, nb.build());
}
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
I schedule the alert like so:
...
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hours);
calendar.set(Calendar.MINUTE, minutes);
AlarmManager alarm_manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlertReceiver.class);
PendingIntent pending_intent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarm_manager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending_intent);
```
The problem is that from Android 8 calling startService from the background is not allowed:
In this code:
public class AlertReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
intent = new Intent(context, NotificationService.class);
context.startService(intent);
}
}
You can change from:
context.startService(intent);
To:
ContextCompat.startForegroundService(getApplicationContext(), intent)
And put this in your Manifest:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
This will at least allow your service to run from the background in your current implementation.
You then have 5 seconds to call startForeground() in your Service and post a Notification that lets the user know that your service is running or it will be terminated.
Also for what you are trying to do, I think you will get a better result with:
setExactAndAllowWhileIdle
Or
setAlarmClock
setExact does not work as the name implies. All the AlarmManager documentation needs to be read carefully and I would suggest studying "doze" in detail before attempting any Service implementations that rely on timing.
This is a notification that I used in a project (sorry for Kotlin language):
private fun createNotification() {
val notification = getServiceNotification("")
notificationManager.notify(NOTIFICATION_ID, notification.build())
}
private fun getServiceNotification(contentText: String): Notification.Builder {
var notification = Notification.Builder(this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel()
notification = Notification.Builder(this, NOTIFICATION_SERVICE_CHANNEL_ID)
}
val openAppPendingIntent = PendingIntent.getActivity(
this,
0,
Intent(this, MainActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT
)
return notification
.setContentTitle("Notification Title")
.setContentText(contentText)
.setSmallIcon(R.drawable.ic_main)
.setContentIntent(openAppPendingIntent)
}
#RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel() {
val notificationChannel = NotificationChannel(
NOTIFICATION_SERVICE_CHANNEL_ID,
NOTIFICATION_SERVICE_CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH
).apply {
lightColor = Color.GREEN
lockscreenVisibility = Notification.VISIBILITY_PRIVATE
}
notificationManager.createNotificationChannel(notificationChannel)
}

Schedule Android function when App is closed at specific time

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.

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.

Categories

Resources