crash (or automatic restart) of service - android

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.

Related

Starting service with Alarm Manager on Android?

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.

Service started again after killed by task manager

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;
}
}

How to schedule an android service to execute at a fixed rate

I am working on an application that should download a file from the network every X seconds to check for any change, I use a service to do that, but its execution is not fixed with the delay time rate, here is my code for the service:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
checkUpdate();
return START_STICKY;
}
private Void checkUpdate() {
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
Log.i("Service", String.valueOf(++counter));
if(Helper.isNetworkAvailable(getBaseContext())) {
// download file
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
}else {
Log.e("Connection", "No connection");
}
}
}, 10000, 10000);
return null;
}
The output isn't fixed, it is supposed to run every 10 seconds, while running the service run in a random manner
How about setting up an AlarmManager within an IntentService? Much more accurate.
Intent intent = new Intent(context, YourClass.class);
PendingIntent pi = PendingIntent.getService(context, 0, intent, 0);
AlarmManager am = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), 10*1000, pi);
Make sure within YourClass.class (which is an IntentService), put your logic in the handleIntent(Intent intent), which will be called every 10 seconds by the PendingIntent sent by the AlarmManager.
P.S. Update your manifest
Hope it helps
Instead of Timer Class, use AlarmManager class. It also performs the same repeating tasks you want. AlamrManager is light weight and it runs even if your device is in sleep mode.
Also see this link Android: How to repeat a service with AlarmManager
For repetitive jobs android provides simple api, called Timer please look it. Very simple to use.
Try this :
#Override
public void onStart(Intent intent, int startId) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Log.d("Internet Available: ", ""+flag);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 10);
Intent intent1 = new Intent(this, UpdateWidgetServiceDemo.class);
PendingIntent pintent = PendingIntent.getService(this, 0, intent1, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int i;
i=15;
alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
super.onStart(intent, startId);
}
REMOVE return START_STICKY;

AlarmManager on being cancelled immediately invokes pending intent

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.

How to stop service at particular time on Android?

Start my service at : 8am. I don't know how to stop service at specific time.
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, MyService.class);
PendingIntent pi = PendingIntent.getService(this,
(int) System.currentTimeMillis(), intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24*60*60*1000, pi);
I want Myservice start at 8am and stop at 6pm in everyday.
Please help me. Thanks.
you could use the AlarmManager, .cancel(PendingIntent intent) at the myService.class, checking whether it's 6pm and cancel the alarm if the intent exists.
Check the API:
Alarm Manager API
This might be an old question but I came across this issue myself today and figured a way to do it:
You can use a new service which stops your service, and start that service in the desired time on a daily basis using alarm manager, like this:
Define the service which will stop your service:
package com.youractivity;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyServiceTerminator extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_NOT_STICKY;
}
public void onCreate()
{
Intent service = new Intent(this, MyService.class);
stopService(service); //stop MyService
stopSelf(); //stop MyServiceTerminator so that it doesn't keep running uselessly
}
#Override
public IBinder onBind(Intent intent) {
//TODO for communication return IBinder implementation
return null;
}
}
add the following code after the one you posted, and run the method inside your activity:
private void stopRecurringAlarm(Context context) {
Calendar updateTime = Calendar.getInstance();
updateTime.setTimeZone(TimeZone.getTimeZone("GMT+3"));
updateTime.set(Calendar.HOUR_OF_DAY, 18);
updateTime.set(Calendar.MINUTE, 0);
Intent intent = new Intent(this, MyServiceTerminator.class);
PendingIntent pintent = PendingIntent.getService(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarms.setRepeating(AlarmManager.RTC_WAKEUP,updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pintent);
}
this way the service will be scheduled to start as you posted above, and scheduled to stop at 6 as shown in the code I posted.
You can use AlarmManager for scheduling and cancel method to stop.
alarmMgr.cancel(alarmIntent);
you can find all your necessary information here
https://developer.android.com/training/scheduling/alarms.html

Categories

Resources