2

This is my code:

Activity:

@Override
public void onCreate(Bundle savedInstanceState) {

...

Intent intent = new Intent(this, MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
    this.getApplicationContext(), 234324243, intent, PendingIntent.FLAG_UPDATE_CURRENT);

AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
    + (5 * 1000), pendingIntent);

...
} 

BroadcastReceiver:

public class MyReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    Intent service = new Intent(context, StartNotificationService.class);

    context.startService(service);
}

Service:

public class StartNotificationService extends Service {

@Override
public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);

    this.intent = intent;
    showNotification();
}

private void showNotification() {
    Date date = new Date(pror.getFirstMillis());

    Log.i("date", date.toString());

    Timer timer = new Timer();
    TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            createNotification(contentTitle, contentText, tickerText);

            pror.calculateVak();
            pror.setFirstMillis(pror.getNextVak());

            createStatusBarNotification(contentTitle, contentText, tickerText);
        }
    };
    timer.schedule(timerTask, date);
}

}

AndroidManifest

<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
     android:icon="@drawable/icon"
    android:label="@string/app_name" >
    <activity android:name=".ShowSettingsActivity" />

    <receiver android:name=".MyReceiver"/> 
    <service android:name=".service.StartNotificationService"/>

    <activity android:name=".PreferencesActivity" android:label="@string/app_name">
   </activity>
    <activity
        android:label="@string/app_name"
        android:name=".VakActivity" >
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

When phone go to sleep, alarmManager can't start notification/service.

If I leave my phone in the 'active' - unlock state, a notification is triggered at a certain time.

Where I made mistake?

Kolesar
  • 1,265
  • 3
  • 19
  • 41

1 Answers1

4

There are two ways to approach it.

  1. If all you're doing is creating a status bar notification, then just do that in your BroadcastReceiver
  2. If you need your service to run prior to making the notification, and you need this to be able to happen while device is asleep, you need to acquire a WAKE_LOCK

So for approach 2 in your class body for the service you need:

PowerManager pm;
PowerManager.WakeLock wl;

Then in your onCreate you need:

pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
wl.acquire();

And then in your onDestroy you need to put:

wl.release();

All this info I got from PowerManager

Reed
  • 14,703
  • 8
  • 66
  • 110
  • 2
    Actually, what you describe is insufficient. The device may well fall asleep between the end of `onReceive()` and the time you acquire the `WakeLock`. That's why I wrote the [`WakefulIntentService`](https://github.com/commonsguy/cwac-wakeful), to have a reusable component that handles this pattern. That being said, I agree that the OP should just put the `Notification` in `onReceive()` and get rid of the `Service` and all the bizarre `TimerTask` stuff. – CommonsWare Jan 14 '12 at 01:39
  • @CommonsWare Yeah, I guess that's true. If it were changed to [`getService`](http://goo.gl/cIK3g), and then OP used the `WakeLock` in `onCreate` of the service, that would work, correct? – Reed Jan 14 '12 at 07:54
  • 1
    Actually, that doesn't work either. Android does not guarantee that it will keep the device awake in that scenario. The only guarantee is *if* you use a `getBroadcast()` `PendingIntent`, *then* the device will stay awake long enough for `onReceive()` to complete. No other scenario has any wakefulness guarantee. Hence, you need to have overlapping `WakeLocks`, acquiring one in `onReceive()` before you return and Android releases its own. In essence, `WakefulIntentService` handles that overlapping `WakeLock` and related issues. – CommonsWare Jan 14 '12 at 12:00
  • @CommonsWare. Can You write one example how can I do that? – Kolesar Jan 14 '12 at 23:54
  • 2
    @Kolesar: There is a `demo/` sub-project in the [`WakefulIntentService`](https://github.com/commonsguy/cwac-wakeful) project that demonstrates the use of `WakefulIntentService`. [Here is a free excerpt](http://commonsware.com/AdvAndroid/wakeful.pdf) from [one of my books](http://commonsware.com/AdvAndroid) that explains more about how `WakefulIntentService` works. – CommonsWare Jan 15 '12 at 00:02
  • @CommonsWare, I've seen and implemented your code(from AdvAndroid-1.0-cc book), but I don't now how can I start an activity in the appservice class that device releases the wakelock after user's response to the activity?! – Behzad Mar 02 '13 at 17:19