Reputation: 5442
I have service running in background with various timertask periodically with interval of 10 mins.
The the service works fine until the application is in foreground and the moment the app get killed the timertask behaves strangely for example not getting called in every 10 mins.
I saw it is common issue and I been through many answers but nothing seems to working for me. Here is my code snippets.Please guide me where I am wrong...
public class myService extends Service
{
@Override public void onCreate()
{
super.onCreate();
myServiceRunningBackground();
service = myService.this;
Log.d(TAG, "myServiceMain");
myServiceRunningBackground();
Message msgObj = serviceHandler.obtainMessage();
serviceHandler.sendMessage(msgObj);
running = true;
}
public final Handler serviceHandler = new Handler()
{
public void handleMessage(Message msg)
{
if(null != serviceTimer)
{
serviceTimer.cancel();
serviceTimer.purge();
serviceTimer = null;
}
serviceTimer = new Timer();
serviceTimer.scheduleAtFixedRate(new myServiceMonitorPower(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
serviceTimer.scheduleAtFixedRate(new myServiceMonitorLocation(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
/* if(target.equals(Target.SERVER))
{*/
serviceTimer.scheduleAtFixedRate(new myServiceMonitorTrafficStats(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
// }
}
};
@Override public int onStartCommand(Intent intent, int flags, int startId)
{
if(intent != null)
{
setTimerInfo(intent.getStringExtra("Current"));
Message msgObj = serviceHandler.obtainMessage();
serviceHandler.sendMessage(msgObj);
}
return START_STICKY;
}
@Override public IBinder onBind(Intent intent)
{
return null;
}
@Override public boolean onUnbind(Intent intent)
{
return super.onUnbind(intent);
}
@Override public void onRebind(Intent intent)
{
super.onRebind(intent);
}
@Override public void onDestroy()
{
super.onDestroy();
running = false;
}
private void setTimerInfo(String check)
{
if(check != null)
{
Log.d(TAG, "Check "+ check);
if (check.equals("enable"))
{
// alarm.SetAlarm(service, 5000);
target = Target.DEVICE;
DELAY_TIMER_TIME = 0;
TIMER_START_TIME = 5000;
}
if (check.equals("disable"))
{
// alarm.SetAlarm(service, 600000);
myServiceRunningBackground();
target = Target.SERVER;
DELAY_TIMER_TIME = 300000;
TIMER_START_TIME = 600000;
}
}
}
private void myServiceRunningBackground()
{
Log.d(TAG,"esServcie ");
final int restartAlarmInterval = 600000;
final int resetAlarmTimer = 2*30*1000;
final Intent restartIntent = new Intent(this, myService.class);
restartIntent.putExtra("ALARM_RESTART_SERVICE_DIED", true);
final AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Handler restartServiceHandler = new Handler()
{
@Override public void handleMessage(Message msg)
{
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 0, restartIntent, 0);
// alarmMgr.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + restartAlarmInterval, pintent);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 10, pintent);
sendEmptyMessageDelayed(0, resetAlarmTimer);
}
};
restartServiceHandler.sendEmptyMessageDelayed(0, 0);
}
public enum Target
{
SERVER,
DEVICE
}
private static boolean running;
public Timer serviceTimer;
private static myService service;
static Target target = null;
public int DELAY_TIMER_TIME = 60000;
public int TIMER_START_TIME = 600000;
private static final String TAG = "myService";
} SO I am using the Alarm manager as well, but does not seems like it is working. I want all the three timertask should be kept running when the application is in background which has the period of 10 mins.
To start and change the mode of services from 5 second to 10 mins I use below code from activity
private void startServices() {
Log.d(TAG, "StartServices ");
Intent intent = new Intent(myActivity.this, myService.class);
intent.putExtra("Current", "enable"); //disable for 10 mins on onDestroy
startService(intent);
}
Thanks for any suggestions
Upvotes: 2
Views: 2869
Reputation: 1873
please see !!!
1.First of all you should save instance of service in Application file
2. You Can also use Alarm after few second if instance is live then no need start service other wise you have need again start SERVICE
It will be helpful for you
Upvotes: 0
Reputation: 506
EDIT: This doesn't act as a service. BUT, if anyone else wants code to run at a scheduled time not as a service, this will work
Overall application class:
public class ExampleApp extends Application {
private SharedPreferences sharedPref;
@Override
public void onCreate() {
super.onCreate();
sharedPref = getSharedPreferences(getString(R.string.preference_file_key), Context.MODE_PRIVATE);
}
private AlarmReceiver alarmReceiver;
private void setAlarm(Long duration) {
sharedPref.edit().putBoolean("alarmSet",true).apply();
alarmReceiver = new AlarmReceiver();
alarmReceiver.setTimer(this, duration);
}
public void cancelAlarm() {
sharedPref.edit().putBoolean("alarmSet",false).apply();
alarmReceiver.cancelTimer(this);
}
}
AlarmReceiverClass
public class AlarmReceiver extends BroadcastReceiver {
private PendingIntent pendingIntent;
private AlarmManager alarmManager;
private Intent intent;
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPref = context.getSharedPreferences(context.getString(R.string.preference_file_key), Context.MODE_PRIVATE);
sharedPref.edit().putBoolean("alarmSet",false).apply();
//TODO: DO YOUR STUFF HERE
}
public void setTimer(Context context, Long addition) {
alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
intent = new Intent(context, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + addition, pendingIntent);
}
public void cancelTimer(Context context) {
alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
intent = new Intent(context, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.cancel(pendingIntent);
}
}
Start from any activity with:
((ExampleApp)getApplication()).setAlarm(10000);
Upvotes: 1
Reputation: 15165
You need to initialize three Timer
s for different schedule. From this snippet:
serviceTimer = new Timer();
serviceTimer.scheduleAtFixedRate(new myServiceMonitorPower(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
serviceTimer.scheduleAtFixedRate(new myServiceMonitorLocation(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
serviceTimer.scheduleAtFixedRate(new myServiceMonitorTrafficStats(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
we can know that serviceTimer
is completely confusing, which TimerTask
will be scheduled. So the solution is, make sure that you initialize 3 Timer
s:
serviceTimer = new Timer();
timer2 = new Timer();
timer3 = new Timer();
serviceTimer.scheduleAtFixedRate(new myServiceMonitorPower(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
timer2.scheduleAtFixedRate(new myServiceMonitorLocation(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
timer3.scheduleAtFixedRate(new myServiceMonitorTrafficStats(service, target), DELAY_TIMER_TIME, TIMER_START_TIME);
And cancel them once your Service
get destroyed:
@Override
public void onDestroy(){
running = false;
serviceTimer.cancel();
timer2.cancel();
timer3.cancel();
super.onDestroy();
}
Using AlarmManager
for short time task may drains the user's battery, use Timer
instead.
Upvotes: 0