4

I still cannot get my AlarmReceiver class' onReceive method to fire. Does anything stick out as wrong with this implementation?

All this is supposed to do is wait a certain period of time (preferably 6 days) and then pop up a notification. (Can you believe there isn't a built in system for this? crontab anyone!?)

MyActivity and BootReceiver both set up an alarm under the necessary conditions. AlarmService kicks out a notification. And AlarmReceiver is supposed to catch the alarm and kick off AlarmService, but it has never caught that broadcast, and won't no matter what I do.

Oh, and I've been testing on my Droid X, 2.3.4. Project being built against API 8.

P.S. Most of this has been adapted from http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/

------------ MyActivity.java ------------

public class MyActivity extends Activity implements SensorEventListener {

    private void setupAlarm() {
        Log.i(TAG, "Setting up alarm...");
        AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, new Intent(context, AlarmReceiver.class), 0);

        // Get alarm trigger time from prefs
        Log.i(TAG, "Getting alarm trigger time from prefs...");
        SharedPreferences mPrefs2 = PreferenceManager.getDefaultSharedPreferences(context);
        long trigger = SocUtil.getLongFromPrefs(mPrefs2, AlarmConst.PREFS_TRIGGER);
        Log.i(TAG, "Trigger from prefs: " + trigger + " (" + new Date(trigger).toString() + ").");

        // If alarm trigger is not set
        if(trigger == new Long(-1).longValue()) {
            // Set it
            trigger = new Date().getTime() + NOTIFY_DELAY_MILLIS;
            SocUtil.saveLongToPrefs(mPrefs2, AlarmConst.PREFS_TRIGGER, trigger);
            Log.i(TAG, "Trigger changed to: " + trigger + " (" + new Date(trigger).toString() + ").");

            // And schedule the alarm
            alarmMgr.set(AlarmManager.RTC, trigger, pendingIntent);
            Log.i(TAG, "Alarm scheduled.");
        }
        // If it is already set
        else {
            // Nothing to schedule. BootReceiver takes care of rescheduling it after a reboot
        }
    }

}

------------ AlarmService.java ------------

public class AlarmService extends IntentService {

   public AlarmService() {
      super("AlarmService");
   }

   @Override
   public void onHandleIntent(Intent intent) {
      Log.i(AlarmConst.TAG, "AlarmService invoked.");
      this.sendNotification(this);
   }

   private void sendNotification(Context context) {
      Log.i(AlarmConst.TAG, "Sending notification...");
      Intent notificationIntent = new Intent(context, Splash.class);
      PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);

      NotificationManager notificationMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
      Notification notification = new Notification(R.drawable.icon, "Test1", System.currentTimeMillis());
      notification.setLatestEventInfo(context, "Test2", "Test3", contentIntent);
      notificationMgr.notify(0, notification);
   }
}

------------ AlarmReceiver.java ------------

public class AlarmReceiver extends BroadcastReceiver {

   // onReceive must be very quick and not block, so it just fires up a Service
   @Override
   public void onReceive(Context context, Intent intent) {
      Log.i(AlarmConst.TAG, "AlarmReceiver invoked, starting AlarmService in background.");
      context.startService(new Intent(context, AlarmService.class));
   }
}

------------ BootReceiver.java ------------ (to restore wiped alarms, because stuff I schedule with the OS isn't important enough to stick around through a reboot -_-)

public class BootReceiver extends BroadcastReceiver {

   @Override
   public void onReceive(Context context, Intent intent) {
      Log.i(AlarmConst.TAG, "BootReceiver invoked, configuring AlarmManager...");


      Log.i(AlarmConst.TAG, "Setting up alarm...");
      AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
      PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, new Intent(context, AlarmReceiver.class), 0);

      // Get alarm trigger time from prefs
      Log.i(AlarmConst.TAG, "Getting alarm trigger time from prefs...");
      SharedPreferences mPrefs2 = PreferenceManager.getDefaultSharedPreferences(context);
      long trigger = SocUtil.getLongFromPrefs(mPrefs2, AlarmConst.PREFS_TRIGGER);
      Log.i(AlarmConst.TAG, "Trigger from prefs: " + trigger + " (" + new Date(trigger).toString() + ").");

      // If trigger exists in prefs
      if(trigger != new Long(-1).longValue()) {
          alarmMgr.set(AlarmManager.RTC, trigger, pendingIntent);
          Log.i(AlarmConst.TAG, "Alarm scheduled.");
      }
   }
}

------------ Manifest ------------

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <activity
        android:name=".MyActivity"
        android:label="@string/app_name" >
    </activity>

<receiver android:name="com.domain.app.BootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

<receiver android:name="com.domain.app.AlarmReceiver"></receiver>

    <service android:name="com.domain.app.AlarmService"></service>
Cœur
  • 37,241
  • 25
  • 195
  • 267
mmseng
  • 735
  • 9
  • 24

3 Answers3

3

Here is some code I recently used to make a notification every hour (This is in my MainActivity):

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent Notifyintent = new Intent(context, Notify.class);
PendingIntent Notifysender = PendingIntent.getBroadcast(this, 0, Notifyintent, PendingIntent.FLAG_UPDATE_CURRENT);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 3600000, Notifysender);

Then in Notify.java

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class Notify extends BroadcastReceiver{

    @SuppressWarnings("deprecation")
    @Override
    public void onReceive(Context context, Intent intent) {
          NotificationManager myNotificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
          Notification notification = new Notification(R.drawable.ic_launcher, "Update Device", 0);
          Intent notificationIntent = new Intent(context, MainActivity.class);
          PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
          notification.setLatestEventInfo(context, "Device CheckIn", "Please run Device CheckIn", contentIntent);
          notification.flags |= Notification.FLAG_HIGH_PRIORITY;
          myNotificationManager.notify(0, notification);
    }
}

Then lastly in the AndroidManifest.xml I have this in between the tags:

<receiver android:name=".Notify" android:exported="true">
         <intent-filter>
                <action android:name="android.intent.action.NOTIFY" />
            </intent-filter>
</receiver>

I have the main code that I know works at the office, feel free to email me for more help as I faced the same issues.

email: sbrichards at mit.edu

sbrichards
  • 2,169
  • 2
  • 19
  • 32
  • Does not work for me, just tried your code. http://stackoverflow.com/questions/15872880/onreceiver-of-broadcastreceiver-not-called-alarmmanager – Siddharth Apr 08 '13 at 14:02
0

You must register your AlarmReceiver with an intent Action. like below. and the action string must be same to what action you are broadcasting by sendBroadcast() method..

like sendBroadcast(new Intent(""com.intent.action.SOMEACTION.XYZ""));

    <receiver android:name="com.domain.app.AlarmReceiver">

<intent-filter>
                <action android:name="com.intent.action.SOMEACTION.XYZ" />
            </intent-filter>
</receiver>
AAnkit
  • 27,299
  • 12
  • 60
  • 71
  • Thanks, but I don't understand where sendBroadcast is supposed to be used. It was my understanding that the AlarmManager would take care of actually sending the broadcast, and that my alarmreceiver would pick it up. Obviously I need to fix my Manifest to add an intent filter to my AlarmReceiver, but I wouldn't know what action to put there, because I don't know what action the broadcast is actually sending. – mmseng Jul 31 '12 at 20:45
-3

I solved this by not even using a BroadcastReceiver. Every single one of the tutorials and posts I read about how to do notification alarms (and that was A LOT) said to use a BroadcastReceiver, but apparently I don't understand something, or that's a load of crap.

Now I just have the AlarmManager set an alarm with an Intent that goes directly to a new Activity I created. I still use the BootReceiver to reset that alarm after a reboot.

This lets the notification work in-app, out-of-app, with the app process killed, and after a reboot.

Thanks to the other commenters for your time.

Chilledrat
  • 2,593
  • 3
  • 28
  • 38
mmseng
  • 735
  • 9
  • 24
  • 4
    Using BroadcastReceiver is important if you are requesting device to wake up when the alarm goes off with either AlarmManager.ELAPSED_REALTIME_WAKEUP or AlarmManager.RTC_WAKEUP. It is guaranteed that the device will stay awake during onReceive but there is no such guarantees for starting a service: device may fell asleep before service actually starts. See [this](http://stackoverflow.com/questions/7444139/wake-service-directly-from-alarmmanager) and [this](http://stackoverflow.com/questions/10206021/alarmmanager-not-working-in-sleep-mode-in-android) questions if you interested. – Darth Beleg Aug 08 '12 at 12:52
  • This question is extremely irrelevant to me at this point, but I'm still getting downvoted on it (9 years later), so I'm "unaccepting" my answer. It worked for my purposes at the time, but clearly I didn't know what I was doing, and didn't receive an answer that guided me to a proper solution. – mmseng Mar 25 '21 at 19:58