I'm using a timer to check the time and set the alarm every 3 minutes so it contains the following line:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
contentIntent = PendingIntent.getBroadcast(getActivity().getApplicationContext(), 12,
my_intent,PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
}
Then I set the alarm using the following code:
alarmMgr.setAlarmClock(new AlarmManager.AlarmClockInfo(calendar.getTimeInMillis(), contentIntent), contentIntent);
The alarm receiver is not called as expected.But if I used that code and set the alarm only one time without a timer it works.So I think FLAG_UPDATE_CURRENT is not working because it works for versions before Android 12 perfectly .If you tested that code using a timer and it works please reply to me...
Related
Okay, I know my title can be confusing so I'll explain a bit. I have access to an API and I would like that: every hour, my application, in the background, makes a request to this API and sends a notification if the API response contains a more or less recent date. To check if the answer is recent, I am already able to do it but what I would like to know is how to make this request in the background every hour and then how to send the data of this request in a notification (I already know how to create a notification, that's not the problem). I'm stuck for some time, I imagine that the answer will be something related to a server, a domain that I know absolutely nothing about
You can try AlarmManager and BroadcastReceiver with the repeating time 1 hour
Example:
val flag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
} else PendingIntent.FLAG_UPDATE_CURRENT
val intent = Intent(context, YourReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, flag)
val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
alarmManager.setRepeating(
AlarmManager.RTC,
timeInMillis,
1000 * 60 * 60, //1h in millis
pendingIntent
)
Then write your YourReceiver and override onReceive function
class YourReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
//call api & check your requirements then push notification
}
}
Manifest:
<application>
...
<receiver android:name=".YourReceiver" />
</application>
Or you can try periodic work request:
https://medium.com/#sumon.v0.0/android-jetpack-workmanager-onetime-and-periodic-work-request-94ace224ff7d
If the API already exists, you don't need a server. You just need to schedule a job to be done on the device every hour. You can use WorkScheduler for that. If the API needs to be written, then yes you need a server and need to learn how to write a web service. But that's well beyond the size of a stack overflow question, you can google for a variety of tutorials on that.
I have an app which needs to do task at the exact time provided just like the stock android alarm clock I have used setExactAndAllowWhileIdle() / setExact(). But BroadcastReciever fires after some minutes and sometimes after opening the app, is there any workaround for it?
Alarm Setter code
// set Alarm
Intent intent = new Intent(this.context, AlarmReceiver.class);
intent.putExtra("alarmInfo", extraInfo);
intent.setAction(Long.toString(System.currentTimeMillis()));
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.context, 123456, intent, 0);
AlarmManager alarmManager = (AlarmManager) this.context.getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, finalTime - 400, pendingIntent);
} else {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, finalTime - 400, pendingIntent);
}
BroadcastReciever
setNextAlarm();
Log.d("RESULT", "fired");
Intent alarmIntent = new Intent(context, AlarmSoundService.class);
// Log.d("extra", "alarmInfo: " + intent.getStringExtra("alarmInfo"));
alarmIntent.putExtra("alarmInfo", intent.getStringExtra("alarmInfo"));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(alarmIntent);
} else {
context.startService(alarmIntent);
}
setNextAlarm() is the previous code I provided which sets the alarm for the future task.
EDIT
Ok so I have solved my problem the first is getting my alarm to fire at the exact moment so setExactAndAllowWhileIdle() / setExact() are both kind of exact so if I need to show user something and have to be accurate
I used the setAlarmClock() as the android doc explains
The system may also do some prep-work when it sees that such an alarm
coming up, to reduce the amount of background work that could
happen if this causes the device to fully wake up
The second problem was that the alarm wasn't firing up unless I open the app this was due to the fact that two alarms were firing between the interval of 5 minutes and since I was using setExactAndAllowWhileIdle()
and the android doc explains
Under normal system operation, it will not dispatch these alarms more
than about every minute (at which point every such pending alarm is
dispatched); when in low-power idle modes this duration may be
significantly longer, such as 15 minutes.
And that was it.
I've programmed an app with multiple alarms using the AlarmManager. I also have a method which cancels all current/pending alarms. It works well, however if the user closes the app from recents (alarms are still active, as intended), my cancel-alarms-method doesn't work anymore (the app crashes). Is there any solution to this? How can I cancel my alarms after the user has closed the app?
This is what my alarms look like:
ArrayList<PendingIntent> intentArray = new ArrayList<PendingIntent>();
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
...
Intent intent = new Intent(this, AlertReceiver.class);
Long cal = new GregorianCalendar().getTimeInMillis() + sms_in_x_minutes * 60 * 1000;
PendingIntent i1 = PendingIntent.getBroadcast(this, intent_id++, intent, 0);
am.set(AlarmManager.RTC_WAKEUP, cal, i1);
intentArray.add(i1);
This is what my cancel-method looks like:
private void cancelAlarms(){
if(intentArray.size()>0){
for(int i=0; i<intentArray.size(); i++){
am.cancel(intentArray.get(i));
}
intentArray.clear();
}
}
My guess is that intentArray and am are empty after I close the app, and the PendingIntents are not saved. But I don't know how to work around that.
Do not keep an array of Pending intents. As you correctly diagnosed, your array is empty after the app is closed which causes a crash when you are trying to access them again.
Set up ONLY the earliest alarm. Save the ID of the alarm to temp storage (e.g SharedPreferences). (If it is easier, you can also use a constant value for the ID as you now only have one alarm to think about)
When your alarm fires, you can set up the next earliest alarm as the first task that is performed.
If you want to cancel your alarm and have an ID value saved in your SharedPreferences, use this to recreate the AlarmManager and cancel the alarm. If there is no ID value then no alarms are set and no cancellation is required.
I think you should add the closing alarm method to the ondestroy method of your app, because if an user closes your app without stopping them, your method will never be called causing the crash of the app.
hope it works :)
EDIT: try to have a look at service and similar. some months ago i did use them in an android app and i remember that even if i close the app from recents, this service still worked and for closing it i had to add a method in app or to stop the process.
If i got it this should be the method you were looking for, sorry if i'm not precise but months passed and i forgot the name of the service i used, i'm just sure it was a service :)
I've read a bunch of answers pertaining to this question and they all seem to be the same:
"Run your service with START_STICKY"
"Run your service in the foreground"
"Run your service with startService and don't bind it"
I'm doing ALL of these things, and my service STILL closes and restarts every time my activity is closed.
This is NOT an IntentService.
I'm also not calling stopSelf or stopService anywhere except in onClick handlers.
Please scroll down to my update - This behavior has been confirmed to be a bug in the android OS and I have reported it to google. Click here to view the report.
Starting my service from MainActivity:
svcIntent = new Intent(getBaseContext(), MyService.class);
startService(svcIntent);
In my onStartCommand:
// Enter foreground state
String title = "Service has been started...";
String subject = "Service is running...";
String body = "Monitoring your battery usage.";
Notification notification = new Notification(R.drawable.theicon, title,
System.currentTimeMillis());
if (prefs.getBoolean("notificationSounds", true))
notification.defaults |= Notification.DEFAULT_SOUND;
else
notification.sound = null;
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, subject, body, pendIntent);
startForeground(1500, notification);
At the end of my onStartCommand:
...
// Release WakeLock
wl.release();
return START_STICKY;
UPDATE
I FIGURED OUT WHATS CAUSING IT! But I have no idea how to fix it. In my service i also use an AlarmManager inside my service to set up function calls to the service a specified time away.
// Alarm manager setup for MyService
AlarmManager AM = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
svcIntent1 = new Intent(this, AlarmReceiver.class);
prefs.edit().putInt("initialBatt", initialBatt).apply();
svcIntent1.setAction("com.myApp.servicealarm");
pendingIntent = PendingIntent.getBroadcast(this, 93, svcIntent1, PendingIntent.FLAG_UPDATE_CURRENT);
// Set the alarm
AM.set(AlarmManager.RTC_WAKEUP, timeNow + waitTime, pendingIntent);
I noticed that if I DO NOT comment out the AM.set call to set an alarm, EVEN WITH AN EMPTY onReceive, my service is killed when the alarm goes off, after I swipe my app away in recent apps. If I comment out the set alarm call, then the service is never killed and keeps running after I close my app. What the heck?! I need this alarm for the functionality of my algorithms!!
It's very odd. As soon as the alarm goes off, my debug message does not print, and my service restarts. But the second time around, after the service restarts, the debug message does print and the program executes successfully.
I've tried this and it still happens with a normal broadcast receiver as well. I've also stripped my code down to ONLY the set alarm call from my service and the broadcast receiver, and the same thing occurs so it's not my algorithm. Apparantly if you have a foreground service that sets an alarm, when the alarm goes off your service restarts.
CLOSING
This behavior seems to be caused by a bug in the android OS so I do not expect an answer. If you'd like to see this bug for yourself, click here. I've provided a project that you can compile and reproduce the problem with.
Android kills the process when the broadcast Intent is sent (before it is received/processed in your app).
This is a nasty Android bug, as of 4.4 (API 19).
See https://code.google.com/p/android/issues/detail?id=63618&can=1&q=service%20restart%20broadcast&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars
especially comments #22 and #23
Unfortunately, almost all "open" issues were marked as "obsolete" recently, with the assumption that they were all fixed in Android 5.0. There's no way for a developer to reopen an "obsolete" issue.
EDIT: Add details about foreground broadcast
Based on the information in the linked issue, it looks like adding Intent.FLAG_RECEIVER_FOREGROUND to your broadcast Intent will ensure that the the process does not get killed on the next receipt of a broadcast Intent.
To do this, add:
svcIntent1.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
to the code where you set your alarm in the AlarmManager.
Please read the comments in the linked issue for more details.
Try to run your service in separate process. Define it in your manifest like this:
<service
android:name=".path.to.service.class"
android:process=":my_service"/>
I am using AlarmManager to do some scheduling task. My problem is, it's not working as it should do. Like, I want to set time for show a toast message ]. If I set, It will be show after 5,10 or 20 minutes. It works fine. But, If I set after 1 hour it will show a toast message.Sometimes, It works properly and sometimes not.Maximum times,it failed.It showed the message right after I hit the set button. I am unable to figure out the problem.Here is my code
Intent myIntent = new Intent(SetSchedule.this,ScheduleReceiver.class);
larmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), PendingIntent.getBroadcas(SetSchedule.this, 1, myIntent,PendingIntent.FLAG_UPDATE_CURRENT));
So, how can I solve the problem ?