Alarm Manager stops trigger PendingIntent after few moments - alarmmanager

I try to create reminder app. My aim is to trigger notification every hour. I have used Alarm Manager to achieve it. Everything works correctly for first 2-3 hours. After that time notifications stop being deliveried. If I reopen app I get missing notification imediatelly.
Alarm Manager:
val intent = Intent(context, AlarmReceiver::class.java).apply {
action = context.getString(R.string.alarm_pending_action)
}
val alarmIntent = PendingIntent.getBroadcast(context, 0, intent, FLAG_UPDATE_CURRENT)
val datetimeToAlarm = Calendar.getInstance()
.apply {
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
datetimeToAlarm.timeInMillis,
60 * 60 * 1000,
alarmIntent
)
AlarmReceiver:
override fun onReceive(context: Context, intent: Intent) {
if (intent.action != null) {
if (intent.action!!.equals(context.getString(R.string.alarm_pending_action), ignoreCase = true)) {
NotificationHelper.createNotification(context)
}
}
}
AndroidManifest
<receiver android:name=".alert.AlarmReceiver"/>
Thank you for your help

I solved my problem. Solution is to replace setRepeating by setAlarmClock and it works well.

Related

Can someone please explain the proper usage of Timers and Triggers in Apache Beam?

I'm looking for some examples of usage of Triggers and Timers in Apache beam, I wanted to use Processing-time timers for listening my data from pub sub in every 5 minutes and using Processing time triggers processing the above data collected in an hour altogether in python.
Please take a look at the following resources: Stateful processing with Apache Beam and Timely (and Stateful) Processing with Apache Beam
The first blog post is more general in how to handle states for context, and the second has some examples on buffering and triggering after a certain period of time, which seems similar to what you are trying to do.
A full example was requested. Here is what I was able to come up with:
PCollection<String> records =
pipeline.apply(
"ReadPubsub",
PubsubIO.readStrings()
.fromSubscription(
"projects/{project}/subscriptions/{subscription}"));
TupleTag<Iterable<String>> every5MinTag = new TupleTag<>();
TupleTag<Iterable<String>> everyHourTag = new TupleTag<>();
PCollectionTuple timersTuple =
records
.apply("WithKeys", WithKeys.of(1)) // A KV<> is required to use state. Keying by data is more appropriate than hardcode.
.apply(
"Batch",
ParDo.of(
new DoFn<KV<Integer, String>, Iterable<String>>() {
#StateId("buffer5Min")
private final StateSpec<BagState<String>> bufferedEvents5Min =
StateSpecs.bag();
#StateId("count5Min")
private final StateSpec<ValueState<Integer>> countState5Min =
StateSpecs.value();
#TimerId("every5Min")
private final TimerSpec every5MinSpec =
TimerSpecs.timer(TimeDomain.PROCESSING_TIME);
#StateId("bufferHour")
private final StateSpec<BagState<String>> bufferedEventsHour =
StateSpecs.bag();
#StateId("countHour")
private final StateSpec<ValueState<Integer>> countStateHour =
StateSpecs.value();
#TimerId("everyHour")
private final TimerSpec everyHourSpec =
TimerSpecs.timer(TimeDomain.PROCESSING_TIME);
#ProcessElement
public void process(
#Element KV<Integer, String> record,
#StateId("count5Min") ValueState<Integer> count5MinState,
#StateId("countHour") ValueState<Integer> countHourState,
#StateId("buffer5Min") BagState<String> buffer5Min,
#StateId("bufferHour") BagState<String> bufferHour,
#TimerId("every5Min") Timer every5MinTimer,
#TimerId("everyHour") Timer everyHourTimer) {
if (Objects.firstNonNull(count5MinState.read(), 0) == 0) {
every5MinTimer
.offset(Duration.standardMinutes(1))
.align(Duration.standardMinutes(1))
.setRelative();
}
buffer5Min.add(record.getValue());
if (Objects.firstNonNull(countHourState.read(), 0) == 0) {
everyHourTimer
.offset(Duration.standardMinutes(60))
.align(Duration.standardMinutes(60))
.setRelative();
}
bufferHour.add(record.getValue());
}
#OnTimer("every5Min")
public void onTimerEvery5Min(
OnTimerContext context,
#StateId("buffer5Min") BagState<String> bufferState,
#StateId("count5Min") ValueState<Integer> countState) {
if (!bufferState.isEmpty().read()) {
context.output(every5MinTag, bufferState.read());
bufferState.clear();
countState.clear();
}
}
#OnTimer("everyHour")
public void onTimerEveryHour(
OnTimerContext context,
#StateId("bufferHour") BagState<String> bufferState,
#StateId("countHour") ValueState<Integer> countState) {
if (!bufferState.isEmpty().read()) {
context.output(everyHourTag, bufferState.read());
bufferState.clear();
countState.clear();
}
}
})
.withOutputTags(every5MinTag, TupleTagList.of(everyHourTag)));
timersTuple
.get(every5MinTag)
.setCoder(IterableCoder.of(StringUtf8Coder.of()))
.apply(<<do something every 5 min>>);
timersTuple
.get(everyHourTag)
.setCoder(IterableCoder.of(StringUtf8Coder.of()))
.apply(<< do something every hour>>);
pipeline.run().waitUntilFinish();

AlarmManager didn't work in oreo and later

I used lots of method from alarmManager like
setRepeating, setInexactRepeating(),setExactAndAllowWhileIdle(),
also this too
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { manager.setAlarmClock(AlarmManager.AlarmClockInfo(c.timeInMillis , null),intentAlarm) }
everything is working well when app is running or in recent, but when i close the app it didn't do anything
I also give manifest permission
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
I look into this stackoverflow question and it didn't work for me
and also from this github project
Please help me i stuck for 3 days and didn't get solution that trigger my alarm when app is closed
here is my full code of implemantation
fun setAlarm(c: Calendar, context: Context, tick:Long, dayChoosen:ArrayList<String>) {
val manager = context.getSystemService(ALARM_SERVICE) as AlarmManager
//Notification Broadcast intent
val intentAlarm = Intent(context, MyReceiver::class.java).let {
it.putExtra("daysChoosenArrayList", dayChoosen)
it.putExtra("id", dayChoosen)
PendingIntent.getBroadcast(context, tick.toInt(), it, PendingIntent.FLAG_ONE_SHOT)
}
//alarm fire next day if this condition is not statisfied
if (c.before(Calendar.getInstance())) {
c.add(Calendar.DATE, 1)
}
//set alarm
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, c.timeInMillis, 24*60*60*1000,intentAlarm)
}
and broadcast receiver
class MyReceiver: BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent?) {
notification(p0!!,"nono")
}
}
notifcation()
fun notification(context: Context, text:String ){
// pendingIntent is an intent for future use i.e after
// the notification is clicked, this intent will come into action
val intent = Intent(context, MainActivity::class.java)
// FLAG_UPDATE_CURRENT specifies that if a previous
// PendingIntent already exists, then the current one
// will update it with the latest intent
// 0 is the request code, using it later with the
// same method again will get back the same pending
// intent for future reference
// intent passed here is to our afterNotification class
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
// checking if android version is greater than oreo(API 26) or not
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(false)
notificationManager.createNotificationChannel(notificationChannel)
builder = Notification.Builder(context, channelId)
.setContentText(text)
.setSmallIcon(R.drawable.ic_launcher_background)
.setLargeIcon(BitmapFactory.decodeResource(context.resources, R.drawable.ic_launcher_background))
.setContentIntent(pendingIntent)
} else {
builder = Notification.Builder(context)
.setContentText("heheh")
.setSmallIcon(R.drawable.ic_launcher_background)
.setLargeIcon(BitmapFactory.decodeResource(context.resources, R.drawable.ic_launcher_background))
.setContentIntent(pendingIntent)
}
notificationManager.notify(1234, builder.build())
}

How do I restrict hours of operation in a rest-based API function?

I have an API integration for our web store running on AWS Lambda to return live delivery quotes based on customer address, and then create the delivery order to a third party delivery as a service provider when the invoice is completed (paid).
I was able to add a time restriction for Monday-Saturday but Sunday has different hours and is not working. Here is the relevant code:
'use strict'
/**
* This function is use to generate qoutes to client 1st warehouse
*/
exports.handler = function (event, context, callback) {
console.log('-------------------EVENT OBJECT--------------------------')
// console.log(event.body.shipping_address)
console.log(event)
try {
const app = require('./app')
const EventEmitter = require('events').EventEmitter
const _bus = new EventEmitter()
let date = new Date()
if (date.getDay() == 0) {
if (!(date.getHours() >= 17 && date.getHours() <= 22) || !(date.getHours() < 3)) {
callback(null, {
message: 'The store is closed'
})
}
} else {
if (date.getHours() >= 3 && date.getHours() <= 15) {
callback(null, {
message: 'The store is closed'
})
}
}
let _shipmentReturn = []
let _shipmentReturnError = []
}
catch(e) {
}
}
Be very careful when using NOT logic.
Your 'normal' days have the store closed from 3am to 4pm. (Yes, 4pm. That's because you only check hours, so 3:59pm is still an 'hour' of 3, so it would be closed.)
On Sunday, the store is closed from midnight to 4:59pm, and also 10pm to midnight.
Take a look at this line:
if (!(date.getHours() >= 17 && date.getHours() <= 22) || !(date.getHours() < 3)) {
Let's pick a time of 2am. It equates to:
if (!(FALSE) || !(TRUE))
This equals TRUE, so the store is closed.
Same for 4am: if (!(FALSE) || !(FALSE)) also equals TRUE
You possibly want an AND rather than an OR in those logic statements.
I would also recommend that you convert the UTC times into your "local" times, which would make it easier for you to write the logic. This will avoid errors where UTC Sunday does not actually align to your 'local' Sunday. For example, if you are UTC-6, then 2am UTC Sunday is not Sunday in your timezone.

What does the "throughput-deadline-time" configuration option do?

I've stumbled on the throughput-deadline-time configuration property for Akka dispatchers, and it looks like an interesting option, however the only mention of it I could find in the whole documentation is the following:
# Throughput deadline for Dispatcher, set to 0 or negative for no deadline
throughput-deadline-time = 0ms
I think we can agree that this is not very helpful.
So what does throughput-deadline-time control, and what impact does it have when on my dispatcher?
So I had a look at the Akka source code, and found this method in the Mailbox that seems to implement the behavior of throughput-deadline-time:
/**
* Process the messages in the mailbox
*/
#tailrec private final def processMailbox(
left: Int = java.lang.Math.max(dispatcher.throughput, 1),
deadlineNs: Long = if (dispatcher.isThroughputDeadlineTimeDefined == true) System.nanoTime + dispatcher.throughputDeadlineTime.toNanos else 0L): Unit =
if (shouldProcessMessage) {
val next = dequeue()
if (next ne null) {
if (Mailbox.debug) println(actor.self + " processing message " + next)
actor invoke next
if (Thread.interrupted())
throw new InterruptedException("Interrupted while processing actor messages")
processAllSystemMessages()
if ((left > 1) && ((dispatcher.isThroughputDeadlineTimeDefined == false) || (System.nanoTime - deadlineNs) < 0))
processMailbox(left - 1, deadlineNs)
}
}
This piece of code makes it clear: throughput-deadline-time configures the maximum amount of time that will be spent processing the same mailbox, before switching to the mailbox of another actor.
In other words, if you configure a dispatcher with:
my-dispatcher {
throughput = 100
throughput-deadline-time = 1ms
}
Then the mailbox of the actors will process at most 100 messages at a time, during at most 1ms, whenever the first of those limits is hit, Akka switches to another actor/mailbox.

Quartz.net daily jobs keeps getting executed every minute

I have the code below. I would expect it to run daily at 17:00 if the config setting was not set otherwise the config setting will be used. So far no issue, the variable is set correctly. However: Instead of daily the job gets executed every minute and I cant figure out why. Is the scheduler not set up correctly?
TimeSpan timeOfExecution;
if (!TimeSpan.TryParse(ConfigurationManager.AppSettings["TimeOfExecution"], out timeOfExecution))
{
timeOfExecution = new TimeSpan(17, 0, 0);
}
var job = JobBuilder.Create<DailyReportJob>()
.WithIdentity("DailyReportJob")
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity("DailyReportTrigger")
.WithDailyTimeIntervalSchedule(s => s.OnEveryDay().StartingDailyAt(new TimeOfDay(timeOfExecution.Hours, timeOfExecution.Minutes)))
.Build();
Scheduler.ScheduleJob(job, trigger);
Scheduler.ListenerManager.AddJobListener(AutofacJobListener);
Scheduler.Start();
The default time for this trigger is every minute, since you haven't specified otherwise.
You can check all the intervals using this code:
var dt = trigger.GetNextFireTimeUtc();
for (int i = 0; i < 10; i++)
{
if (dt == null)
break;
Console.WriteLine(dt.Value.ToLocalTime());
dt = trigger.GetFireTimeAfter(dt);
}
If you want to schedule your job to run once a day at 5pm, you can change your code adding a 24 hour interval:
var trigger = TriggerBuilder.Create()
.WithIdentity("DailyReportTrigger")
.WithDailyTimeIntervalSchedule(s => s.OnEveryDay().StartingDailyAt(new TimeOfDay(timeOfExecution.Hours, timeOfExecution.Minutes)))
.WithIntervalInHours(24)
.Build();