I've various options to sync data between android app and server. I'm using AlarmManager to trigger sync with user choices. I've one which says Never Update (Update Manually) in which i cancel with toStopServiceAlarm() the AlarmManager.
Que:
It's working fine as long as my application won't be killed by any task manager. As soon as it's killed by Task Manager application service again started with Never Update(Update Manually) where i already cancelled any AlarmManager trigger.
Can anybody help me in preserving my application behaviour even if it's killed by Task Manager? Sync get called as per user choice only.
Code Snippet:-
public class ServiceAlarm extends WakefulBroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, UploadData.class); //UploadData is my service
startWakefulService(context, service);
}
public void startServiceAlarm(String times)
{
context = SmartConsultant.getApplication().getApplicationContext();
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(SmartConsultant.getApplication().getApplicationContext(), UploadData.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 21);
calendar.set(Calendar.MINUTE, 00);
switch(Integer.parseInt(times))
{
case 0://midnight
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
break;
... cases for different interval of sync
}
}
public void toStopServiceAlarm(String times)
{
if (alarmMgr != null) {
alarmMgr.cancel(alarmIntent);
}
}
As per CommonsWare, I just need to override onStartCommand() with START_NOT_STICKY which will make my service loosly tight with Android and won't start once it's killed by TaskManager. That's what behaviour expected from that running Service.
Code Snippet:
public class UploadData extends Service
{
...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
super.onStartCommand(intent, flags, startId);
return START_NOT_STICKY;
}
}
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;
Hi a read other question retated to this but the responses never resolve my issue.
I want to start a service after a specific time with an Alarm Manager
alarmMgr = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmServiceIntent=new Intent(ListActivity.this, AlarmLevelServiceImproved.class);
alarmServiceIntent.putExtra("username",usernameID);
alarmServiceIntent.putExtra("password",userPass);
alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmServiceIntent, 0);
. . .
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND,10);
//calendar.set(Calendar.HOUR_OF_DAY, 19);
//alarmMgr.setInexactRepeating(AlarmManager.RTC,calendar.getTimeInMillis(),
// AlarmManager.INTERVAL_HALF_HOUR,alarmIntent);
//alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
// 1000 * 10, alarmIntent);
alarmMgr.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), alarmIntent);
Log.d("MioLog", "Alarm setted");
My service is:
public class AlarmLevelServiceImproved extends Service {
#Override
public void onCreate() {
Log.d("MioLog","MyAlarmService.onCreate()");
Toast.makeText(this, "MyAlarmService.onCreate()", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent intent) {
Log.d("MioLog","MyAlarmService.onBind()");
Toast.makeText(this, "MyAlarmService.onBind()", Toast.LENGTH_LONG).show();
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d("MioLog","MyAlarmService.onDestroy()");
Toast.makeText(this, "MyAlarmService.onDestroy()", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MioLog","MyAlarmService.onStart()");
Toast.makeText(this, "MyAlarmService.onStart()", Toast.LENGTH_LONG).show();
return super.onStartCommand(intent, flags, startId);
}
}
And I add this on AndroidManifest.xml (The service class is on the sub-package "services"):
<service
android:name=".services.AlarmLevelServiceImproved"
android:enabled="true" />
But the service don't start and no log is printed.
Any idea how to start a Service with the AlarmManager?
I also suived this tutorial but I don't find any difference to my code
Thanks
To start a service with a PendingIntent, you need to use the static method PendingIntent.getService() to retrieve the appropriate PendingIntent.
Your code seems to be using PendingIntet.getBroadcast() for whatever reason. If you intend to have the AlarmManager indeed send a broadcast, you can start your service in your BroadcastReceiver, else change that line to getService():
from
alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmServiceIntent, 0);
to
alarmIntent = PendingIntent.getService(getApplicationContext(), 0, alarmServiceIntent, 0);
You are using getBroadcast() to create the PendingIntent, but the Intent points to a service. That combination will not work.
Since you are using RTC_WAKEUP, you need to use getBroadcast() and a WakeLock to get reliable results. One approach is to use WakefulBroadcastReceiver as the base class of your receiver, where you then forward the work onto an IntentService.
Also, please do not pass user names and passwords in extras, as those are visible to anything that gets its hands on the Intent or PendingIntent. In this case, that should just be your app and the core OS, but I would still aim to do something a bit more secure.
Hi i need to stop the Background service which is already started after particular time.I will get the duration from server for when to stop the service.I have tried the Alarm Manager in android.
Calendar cal = Calendar.getInstance();
Intent intent = new Intent(context, MyService.class);
PendingIntent pintent = PendingIntent.getService(context, 0, intent, 0);
AlarmManager alarm = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
// Start every 30 seconds
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 60*1000, pintent);
Log.e(TAG, "Service started in Activity");
This above code is starting the service after every one minute.But i dont want to start the service.I need to stop the service after a minute.How to do that.Is that possible to do with Alarm Manager.Please guide me.
Try that:
add parameter to your pendingIntent
Intent intent = new Intent(context, MyService.class);
intent.putExtra("param_name", "end");
PendingIntent pintent = PendingIntent.getService(context, 0, intent, 0);
Override onStartCommand() method in your Service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try{
String parameter = intent.getStringExtra("param_name");
if(parameter.equals("end")){
stopSelf();
}
}catch(Exception ex){
}
}
Also you can try to use Handler in your service:
Handler variable:
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1: {
stopSelf();
}break;
}
}
}
Delayed task:
handler.sendEmptyMessageDelayed(1, 60 * 1000);
Create the timer task to stop the service and assign the delay time which you are getting from your server
Timer timer = new Timer ();
TimerTask hourlyTask = new TimerTask () {
#Override
public void run () {
// your code here to stop the service ...
}
};
// schedule the task to run assign the time (DelayTime) which you are getting from server
timer.schedule (hourlyTask, DelayTime);
So what is the particular time.
You can do 1 thing make note of the starting time of the service. and if you want to stop the service after a specified duration or the specific time get the system current time compare it with that time if it match's stop the service. this should resolve the problem.
Tell me if it works for you..
======>
Just Follow the steps provided steps below:
Use sharedprefrence to save the start time of the service.
If your not familiar to shearedprefrence URL:http://examples.javacodegeeks.com/android/core/content/android-sharedpreferences-example/
Then in the service onStart method get the system current time if it
matches the time stop the service.
You have to create an broadcast receiver:
Calendar cal = Calendar.getInstance(); // this will return current time
// if you want to trigger after 1 minute then add into calender object
cal.add(Calendar.MINUTE, 1);
Intent intentAlarm = new Intent(this, AlarmReciever.class);
intentAlarm.setAction("My_Action");
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
MainActivity.this, REQUEST_CODE, intentAlarm,
PendingIntent.FLAG_UPDATE_CURRENT);
// set the alarm for particular time
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
AlarmReciever .java
public class AlarmReciever extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// call method to stop service
}
}
Also declare this AlarmReceiver class in menifest file
<receiver android:name=".AlarmReciever" >
</receiver>
> here i used the countdowntime for 30second
after 30second call stopself() method it will stop your
services..u can also do what ever u want on finsih you can also pass a
notification to the user....
new CountDownTimer(30000, 1000) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
//r u can also pass a notification
stopSelf();
}
}.start();
So I have a section of code that schedules an alarm as follows
public void scheduleAlarm(){
Log.d("Scheduler","Alarm is being scheduled");
Intent intent = new Intent(AlarmSettings.this, VolumeService.class);
intent.putExtra("MODE", mode);
PendingIntent pintent = PendingIntent.getService(AlarmSettings.this, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Log.d("Alarm ID:", String.valueOf(id));
Log.d("Time", "Time was set for today: " + String.valueOf(time));
if(time < System.currentTimeMillis()){
time += (DAY);
Log.d("Time", "Time was set for tomorrow: " + String.valueOf(time));
}
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, time, pintent);
}
The service that is being called is as follows
public class VolumeService extends Service{
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//My Service code goes here and makes changes to some settings
Log.d("Service", "settings have been changed");
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
and finally the portion of code that is supposed to cancel the alarms (stay with me, I know its lengthy)
//Unschedule the alarm that is getting deleted
Log.d("Unscheduler", "Alarm is being unscheduled");
Intent uIntent = new Intent(AlarmSettings.this, VolumeService.class);
PendingIntent uPintent = PendingIntent.getService(AlarmSettings.this, id, uIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager uAlarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
uAlarm.cancel(uPintent);
uPintent.cancel();
Now, my problem is that when the user deletes an alarm and subsequently calls the unschedule portion of the code, the volumeService is immediately called and the settings are changed. However, this defeats the purpose of the user deleting the alarm as they will only delete it to prevent it from firing and changing the settings. I have checked everywhere imaginable over the course of weeks and am just beating my head against the wall. Now that I have posted it on here though, it will be that I have made a very simple mistake. In any case, thanks for the help in advance!
--edit #1--
Removed the line uPintent.cancel() in the unscheduler portion and still doesn't work.
I've a service that runs after the Android devices boots up. This executes two notifications every day. But I've a problem: It looks like the the service crashes or automatically restarts. Also the notifications are not executed at the specified time. How can I fix this? Sometime I see the toast Service Created and Service Started. Thanks!
The code:
public class UnUsedService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "Service Created", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
private PendingIntent pendingIntent;
#SuppressWarnings("deprecation")
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.HOUR_OF_DAY, 05); //midday
cal1.set(Calendar.MINUTE, 45);
cal1.set(Calendar.SECOND, 00);
Calendar cal2 = Calendar.getInstance();
cal2.set(Calendar.HOUR_OF_DAY, 17);//8pm for example
cal2.set(Calendar.MINUTE, 30);
cal2.set(Calendar.SECOND, 00);
AlarmManager am = (AlarmManager)getApplicationContext().getSystemService (Context.ALARM_SERVICE);
Intent intent2 = new Intent(getApplicationContext(), AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(),cal2.getTimeInMillis(), pi);
}
};
If your notices need to run at a particular time, you should be using AlarmManager to schedule them. This gets retained by Android, so that your service is free to be killed and the alarm will restart it when necessary.
It sounds like you're currently letting your service run 24/7 just so that it can do something twice a day; this is being a bad Android citizen! Using the AlarmManager instead will fix your problem and also let you stop wasting resources.