2

I have a service which should be run for example every 1 minute. I used a broadcast receiver and AlarmManager to make this work. And also I call PowerManger.aquire() to make sure cpu doesn't sleep before the service starts. For first 2 or 3 days the app runs okay but after that the service doesn't get started. Sounds alarmManager doesn't start it. Any Idea why?

public class MyReceiver extends BroadcastReceiver {
    PowerManager pawerManager;
    public static PowerManager.WakeLock wakeLock=null;
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
         pawerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         wakeLock = pawerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
         wakeLock.acquire();
         Intent serviceIntent=new Intent(context,MyService.class);
         context.startService(serviceIntent);
    }
}

And The Service:

public class MyService extends Service {
    void releaseTheLock(){
        if (MyReceiver.wakeLock != null){
            MyReceiver.wakeLock.release();
            MyReceiver.wakeLock=null;
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub      
        return null;
    }
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub      
        super.onCreate();       
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        final Context serviceContext=this;      
        new Thread(new Runnable() {         
            @Override
            public void run() {
                // TODO Auto-generated method stub      
                    /*
                       Do something
                    */
                    //Now set the timer
                    long currntTime = System.currentTimeMillis();
                    AlarmManager mgr=(AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
                    Intent i= new Intent(serviceContext, MyReceiver.class);
                    PendingIntent pi=PendingIntent.getBroadcast(serviceContext, 0, i, 0);                       
                    mgr.set(AlarmManager.RTC_WAKEUP, currntTime + 60000 , pi);                      
                    stopSelf();
                    releaseTheLock();
                    return;                 

            }
        }).start();
    return START_STICKY;
    }   
}

And here's the receiver registration in manifest:

<receiver android:name=".TimeReceiver"></receiver>
user2808671
  • 271
  • 2
  • 13
  • Post your manifest. How is your `BroadcastReceiver` started/registered with the system? – Larry Schiefer Aug 15 '14 at 17:24
  • Please read the question again. I updated the post. – user2808671 Aug 15 '14 at 17:45
  • What is actually registering your receiver? That's what I'm driving at here - if your receiver is being registered by the service itself, it won't necessarily stick around. The system's low memory killer can decide to kill your process (hosting the service and BR) at any time. So unless your BR is registered via the manifest (which you cannot do for time ticks!) then you're not guaranteed to have your process stick around. – Larry Schiefer Aug 15 '14 at 18:27
  • @LarrySchiefer You can see my receiver is statically registered in the manifest file. See end of the post. – user2808671 Aug 15 '14 at 18:35
  • Actually, it's not registered to receive anything. There is no intent filter, just a receiver declaration. If it were obvious or clear, I wouldn't request it. – Larry Schiefer Aug 15 '14 at 19:19
  • So what should I do? If I define a custom intent-filter for the receiver and then call myIntent.addAction("MY-CUSTOM-INTENT") then attach then pass it to pending intent, the app works correctly? Please share some solutions. I should mention this kind of registering broadcast receiver is common for this kind of internal usage I think. – user2808671 Aug 15 '14 at 19:24
  • OK, I see what you're doing now. It wasn't obvious to me how your service was being started in the first place, which is what I was asking. I'll add an answer below. – Larry Schiefer Aug 15 '14 at 20:34

2 Answers2

3

I suspect you're running into a race condition where the Service object (Context) is being cleaned up and destroyed, but is being used as the Context for your PendingIntent. Here are a couple of options:

  1. Change your creation of PendingIntent to use the application context. This context is the the one in which your PendingIntent is sent. So if you use a transient context, like the Service object itself, it may no longer be valid.

  2. Revise this to not use the BroadcastReceiver at all. You can create a PendingIntent for your Service via the PendingIntent.getService() method. Again, use your application context here rather than the Service object itself.

Larry Schiefer
  • 15,687
  • 2
  • 27
  • 33
  • 1
    The reason that I use broadcast receiver it's because if I pass the service directly instead of broadcast receiver to pending intent then if the device is in sleep mode, the service won't succeed to complete its operation. Please refer to these links: http://stackoverflow.com/questions/15905099/alarm-does-not-wake-up-my-service?answertab=votes#tab-top http://stackoverflow.com/questions/10206021/alarmmanager-not-working-in-sleep-mode?answertab=votes#tab-top but about the context, I'll use getApplicationContext() instead of serviceContext to see what happens. – user2808671 Aug 15 '14 at 21:11
  • Fair enough, I'd forgotten about the wakelock behavior w/services. Good luck! – Larry Schiefer Aug 15 '14 at 21:48
  • There were other problems in my code and I successfully fixed them and the the program is working now. Anyway to close this question I accept this answer. Thanks buddy – user2808671 Aug 27 '14 at 09:20
  • 5
    @user2808671 can you please mention what the problems were that you fixed? – Sharjeel Ahmed Jan 17 '16 at 10:27
  • @user2808671 Follow up, what did you find out? – Ruchir Baronia Jul 25 '18 at 04:43
  • @SharjeelAhmed +RuchirBaronia It's been a couple of years since I posted this and I accidentally got back to this site and found out there are some new comments here. I don't exactly remember the source of the problem but I think it was a subtle logical bug in my background service that caused a function to throw an unexpected exception in a special condition. The condition happened after a few days and messed up some local variables I think (maybe because of too big values). – user2808671 Aug 18 '18 at 04:02
1

Have you tried with setRepeating?

alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        1000 * 60, alarmIntent);
frogatto
  • 28,539
  • 11
  • 83
  • 129
Ariel Carbonaro
  • 1,529
  • 1
  • 13
  • 25
  • No I haven't. But what's the problem with using set() function with RTC_WAKEUP? I want to find the problem. This is strange that program works for 2 or 3 days. – user2808671 Aug 15 '14 at 17:43
  • Like set(int, long, PendingIntent), except you can also supply a period at which the alarm will automatically repeat. This alarm continues repeating until explicitly removed with cancel(PendingIntent). from: http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating(int, long, long, android.app.PendingIntent) – Ariel Carbonaro Aug 15 '14 at 17:48
  • 1
    Thanks but if I want to check if your solution is working or not I should wait for another 3 days. But I wanna understand why my code stops working after some days. If I find and understand the problem I can avoid such incidents for my other apps. I don't want to find only a solution to fix this problem. – user2808671 Aug 15 '14 at 17:57
  • @user2808671 did you get any solution? as my apps alarm stop working after 3days of use and not using app for 3days. – Saloni Parikh Aug 28 '20 at 05:26