I am having a problem with trying to schedule my service to run every so often. I have gotten my service to start on boot, but for what ever reason when the schedule starts is starts the service way to many times.
public class PPPService extends Service {
public void onStart(Intent intent, int startId) {
//TODO do something useful
Log.v("TEST", "Service started");
// Schedule the alarm!
PendingIntent mAlarmSender = PendingIntent.getService(this, 0, intent, 0);
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, AlarmManager.INTERVAL_FIFTEEN_MINUTES, mAlarmSender);
this.stopSelf();
}
}
Resolved: This was resolved by creating a Scheduler instead of having my service schedule itself.
You are sending in the PendingIntent the context of your service that will be killed very soon along with the intent which started it. I guess this can be quite unpredictable. Try getting the pending intent like this:
mAlarmSender = PendingIntent.getService(getApplicationContext(), 0, new Intent(getApplicationContext(), PPPService.class), 0);
Related
I have made a simple example where a toast message will be shown after a time gap. I am using alarmmanager for scheduling a service from where the toast message will be shown. Now the problem is when the app is running it works properly, but when I close the app from task-manager the service is not getting restarted. Below is my service code
public class AlarmService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Alarm Alarm Alarm", Toast.LENGTH_SHORT).show();
return Service.START_STICKY;
}
}
and below is my alarmmanager code :
alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmService.class);
pendingIntent = PendingIntent.getService(this, 0, intent, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 10, pendingIntent);
Now, what is the solution for this? I need to keep the alarm even I close the app.
You can actually implement BroadcastReceiver at onDestroy to restart the service once the app/service is close by the system/user.
You can check the post here, and a tutorial for you, check here.
Hope it helps!
Try with below :-
return Service.START_CONTINUATION_MASK;
My ReminderService uses the AlarmManager to inform the user about an upcoming event at a specific time. Is it possible that the AlarmManager informs the same service (ReminderService) or do I need to start another service to catch the pending intent? Until now this mechanism looks like this
public class ReminderService extends Service {
// ...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// ..
/* When the alarm goes off the NotifyService will be started. Is it possible to inform **this**
service (ReminderService) and to handle the alarm? */
Intent alarmIntent = new Intent(this, NotifyService.class);
alarmIntent.putExtra(TodoTask.PARCELABLE_KEY, task);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, alarmIntent, 0);
Calendar calendar = Calendar.getInstance();
Date date = new Date(reminderTimeStamp*1000);
calendar.setTime(date);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
}
yes u can. You just need to change this line:
Intent alarmIntent = new Intent(this, NotifyService.class);
to this:
Intent alarmIntent = new Intent(this, ReminderService.class);
that way the ReminderService will receive the intent with TodoTask.PARCELABLE_KEY inside this same method public int onStartCommand(Intent intent, int flags, int startId)
Remember that there no guarantee that this will be the same instance of the service. If the service you're running get killed by the system a new instance of it will be started to handle the intent.
Also remember all the sleep and doze mode stuff mentioned by Larry_Schiefer on his answer.
You can use the same Service (or other component) to receive an alarm. However, not that your alarm will not be guaranteed to be delivered on schedule when in low power. Use a WakefulReceiver or your own combination of BroadcastReceiver and a wakelock to get your Service going. See this article for more details on power state and alarms.
Also, note that starting with Android Marshmallow your wakelocks will be ignored if the device is in Doze mode. There are other things you'll have to do to wake the device at a certain time when in Doze.
with a BroadCastReceiver, I execute a service at the smartphone boot:
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Intent startServiceIntent = new Intent(context, MyService.class);
context.startService(startServiceIntent);
}
}
MyService:
private Runnable myRunnable = new Runnable() {
public void run() {
parsing.cancel(true);
parsing = new Parsing();
parsing.execute();
handler.postDelayed(this, timeoutUpdate);
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
handler.removeCallbacks(myRunnable);
handler.postDelayed(myRunnable, 1000);
return Service.START_STICKY;
}
The service is really executed at the boot, but if I set a timeout of 1 hour between executions, service is not executed (maybe the system is killing it). Otherwise, if I set 60 sec between repetition, all works.
How can I do it? Thanks.
You may run the service in the foreground using startForeground().
A foreground service is a service that's considered to be something
the user is actively aware of and thus not a candidate for the system
to kill when low on memory.
But bear in mind that a foreground service must provide a notification for the status bar (read here), and that the notification cannot be dismissed unless the service is either stopped or removed from the foreground.
Note: This still does not absolutely guarantee that the service won't be killed under extremely low memory conditions. It only makes it less likely to be killed.
OR
If you dont want to run the service in the foreground then you can run service in a periodic intervals using AlarmManager
Intent intent = new Intent(context, MyService.class);
PendingIntent pintent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager alarm = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_HOUR, pintent);
Update
Cancel the registered event by using
Intent intent = new Intent(context, MyService.class);
PendingIntent pintent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager alarm = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pintent);
To schedule a job use AlarmManager in BroadcastReciever.
Intent intent = new Intent(context, MyService.class);
PendingIntent pintent = PendingIntent.getService(context, 0, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm. setRepeating(AlarmManager.RTC_WAKEUP, triggerInMillis, intervalMillis, pintent);
System will awake your service and then you will be able to execute task immediately.
set highest priority for your service
<intent-filter
android:priority="integer" >
</intent-filter>
The value must be an integer, such as "100". Higher numbers have a higher priority. The default value is 0. The value must be greater than -1000 and less than 1000.
I have an alarm that is started inside the onCreate() method of the MainActivity. It performs a background service that periodically fetches data from the internet every 20 minutes. It works okay. But the problem is that every time the user exits the application and opens it again, the alarm is set again and the background service is started. So, there are multiple alarms running and the services are run at random intervals. How do I start the alarm only if one isn't running already? I've searched on the internet and found something called PendingIntent.FLAG_NO_CREATE but I can't seem to use it properly. Any help would be appreciated. Here is my Alarm code which is inside the onCreate() method.
/**** CODE FOR BACKGROUND SERVICE ****/
Intent alarm = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarm, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating
(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 1200000, pendingIntent);
/**** END CODE FOR BACKGROUND SERVICE ****/
Yes, you need to use PendingIntent.FLAG_NO_CREATE . Have you tried to implement it like this?
/**** CODE FOR BACKGROUND SERVICE ****/
Intent alarm = new Intent(this, AlarmReceiver.class);
// Check if the alarm receiver is currently active
boolean alarmRunning = (PendingIntent.getBroadcast(this, 0, alarm, PendingIntent.FLAG_NO_CREATE) != null);
if(alarmRunning == false) {
// Alarm is not running. Set it up
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarm, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating
(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 1200000, pendingIntent);
}
else {
// Alarm is running..
Log.d("ALARM TAG", "Alarm is already running. Do nothing.");
}
/**** END CODE FOR BACKGROUND SERVICE ****/
The code snippet below....
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
///////////Do something////////////////////////
showtext.startScan();
//SEt Alarm
Intent intent = new Intent(this, TextReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+9000, pi);}
And my Receiver :
TextReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
///Show text/////
}
}
The thing is that when I run the program after 9sn, I am getting an error that "The app stopped unexpectedly". Why I get this error?
My goal is to show the text every 9sn. What is the correct usage of AlarmManager in the main activity
OR Should I set alarm in the BroadcastReceiver ?
Which one does makes sense: am.setRepeating or am.set in terms of my goal?
**Edit: How can I change my alarm code to run in the Broadcast Receiver ? **
//try this
AlarmManager am=(AlarmManager)getApplicationContext getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),(9 * 1000), pendingIntent);
Never, ever use FLAG_CANCEL_CURRENT with PendingIntents that are set as alarms.
What happens is that you wind up canceling the validity of the PendingIntent currently held by the alarm manager, and this means that the alarm manager can no longer tell that any newly-set alarm matches that old PendingIntent. You wind up with the old (invalid) alarm still registered along with your new one. If you keep doing this you can wind up with hundreds (or more!) stale alarms registered in the system, none of which will actually do anything but which are taking up memory and CPU.