1

The application is pretty simple. I have a regular app with all the activities etc...

I have a service that launches the first time the application starts and/or on device reboot.

I have a BroadcastReceiver set up to handle the notification intent and it's pretty basic as well and functions perfectly.

The notification works perfect when the display on the android device is on. But when I turn the screen off, the notifications are no longer created.

I am new to notifications so it's probably something simple I've overlooked, but I can't seem to find it.

In my service I construct a worker thread which contains a Timer which fires once a minute and takes a TimerTask as part of the schedule method:


@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
    boolean isStopping = false;
    if (intent != null)  // if the system has to shut us down, go down gracefully
    {
        String intentAction = intent.getStringExtra(AppData.BROADCAST_ACTION);
        if (intentAction != null && intentAction.equals("android.intent.action.REBOOT"))
        {
            boolean isRebooting = intent.getBooleanExtra(AppData.SYSTEM_ACTION, false);
            if (isRebooting)
            {
                isStopping = true;
                stopSelf();
            }
        }
    }

    if (!isStopping && !_workerThread.isRunning())
    {
        _workerThread.run();
    }

    return Service.START_STICKY;
}

_timer.schedule(_service.getWorker(), startDelay, executionDelay);

The NotificationTask (TimerTask) ultimately gets fired every minute from the Timer. It then checks some logic to see if any of the notifications need to be created, if so, it creates and sends the notifications like this:


Notification notification = new NotificationCompat.Builder(_context)
        .setContentTitle(getString(R.string.notification))
        .setContentText(message)
        .setLargeIcon(decodeResource(_context.getResources(), iconId))
        .setSmallIcon(R.drawable.logo_mark)
        .setTicker(ticker)
        .setAutoCancel(true)
        .setSound(getRingtone(ringtoneUrl))
        .setVibrate(VIBRATION_PATTERN)
        .setLights(0xfff89829, 300, 5000)
        .setContentIntent(intent)
        .build();

_notificationManager.notify(notificationId, notification);

The notifications are unique by the types of notifications and I don't care if the user has responded to one before I overwrite with the next. My problem is I don't get the notifications if the screen is off.

Please help.


UPDATE

I wanted to add code in case someone gets as stuck as I did.

Let's start with the AndroidManifest. Include 2 BroadcastReceivers and your service


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

<service android:name=".services.NotificationService"/>

<receiver android:name=".receivers.BootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>
<receiver android:name=".receivers.NotificationReceiver" />

The boot receiver is just going to schedule your Alarm when your device gets rebooted. You set it up to call your other receiver like so:


AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, new Intent(context, NotificationReceiver.class), 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance(), 60 * 1000, pendingIntent);

The main receiver is going to launch your service - your service should extend the IntentService instead of the regular Service. Here is the main receiver:


context.startService(new Intent(context, NotificationService.class));

And the service


public class NotificationService extends IntentService
{
    public NotificationService()
    {
        super("Notification Service");
    }

    @Override
    public void onHandleIntent(Intent intent)
    {
        // this is where I created my notifications
    }
}

The last little trick is to create your AlarmManager again in your application. This will replace the AlarmManager that may have been created in the Boot Receiver. Notice PendingIntent.FLAG_CANCEL_CURRENT. This is done so when the user launches your application, your AlarmManager gets registered if it wasn't already registered on a device boot.


AlarmManager alarmMgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, NotificationReceiver.class), PendingIntent.FLAG_CANCEL_CURRENT);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, Utils.getNow(), 60 * 1000, pendingIntent);

Hope this helps.

farcrats
  • 775
  • 7
  • 11

1 Answers1

2

Not saying you're doing it wrong, because I don't have much experience with Timers and TimerTasks, but I thought AlarmManager was the standard way of scheduling things to run in the future, when the screen is off, etc.

ajpolt
  • 1,002
  • 6
  • 10
  • I thought about revising the code to use an AlarmManager, but I was more familiar with a Timer. Do you know if this is my problem? I thought a Notification was a Notification, but alas, I do not know. I will read more about the AlarmManager. – farcrats Nov 01 '12 at 01:42
  • After further review, it appears that Android pauses these threads to conserve battery. I will revise my code to use AlarmManager. If/when this works, I will mark this as the correct answer. – farcrats Nov 01 '12 at 02:24
  • Yes, what I was saying was that the problem wasn't with your notifications but that they were not being created in the first place. Hopefully that helped. – ajpolt Nov 01 '12 at 14:31
  • It turns out you don't need a service quite like this. It's easiest to set up two BroadcastReceivers. One for device boot and one that the boot receiver calls as well as the application calls. I found this [StackOverflow](http://stackoverflow.com/questions/3859489/android-running-a-background-task-using-alarmmanager) that has a link to a project that shows it pretty good – farcrats Nov 01 '12 at 19:48