Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create timed notification (e.g. for events) in Android

For some Android applications, I would like to integrate the following feature: The user can define a time when he wants to be reminded of something. When the time has come then, the application should create a notification in the notification bar even when the user doesn't use the app at this moment.

For this purpose, the classes AlarmManager, NotificationManager und Notification.Builder are the ones to look at, right?

So how do I create a timed notification in advance? My code (so far) is this:

Add this under to the AndroidManifest to register the broadcast receiver:

<receiver android:name="AlarmNotificationReceiver"></receiver>

Create a new class file which handles the alarm that it receives:

public class AlarmNotificationReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {
        Bundle extras = intent.getExtras();
        if (extras != null) {
            String additionalData = extras.getString("displayText");
            // show the notification now
            NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
            Notification mNotification = new Notification(R.drawable.ic_launcher, context.getString(R.string.app_name), System.currentTimeMillis());
            PendingIntent pi = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0); // open MainActivity if the user selects this notification
            mNotification.setLatestEventInfo(context, context.getString(R.string.app_name), additionalData, pi);
            mNotification.flags |= Notification.FLAG_AUTO_CANCEL | Notification.DEFAULT_SOUND;
            mNotificationManager.notify(1, mNotification);
        }
    }

}

Use this code (for example in MainActivity) to set the alarm to 3 seconds from now:

    Intent i = new Intent(this, AlarmNotificationReceiver.class);
    i.putExtra("displayText", "sample text");
    PendingIntent pi = PendingIntent.getBroadcast(this.getApplicationContext(), 234324246, i, 0);
    AlarmManager mAlarm = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    mAlarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+3*1000, pi);

What do I need to change to make this work? Thank you!

The two problems are:

  1. The notification's text does not change when I change it in code. It only changes when I change the requestCode in PendingIntent.getBroadcast(...). What is this request code all about? Can it be a random value or 0?
  2. After rebooting my phone, the "planned" notification, or the alarm, is gone. But now I've seen that this is normal behaviour, right? How can I circumvent this?
like image 336
caw Avatar asked Jan 06 '12 01:01

caw


People also ask

What is notification in Android with example?

A notification is a message you can display to the user outside of your application's normal UI. When you tell the system to issue a notification, it first appears as an icon in the notification area. To see the details of the notification, the user opens the notification drawer.


2 Answers

Not sure about part 1, but for part 2 the general approach is to intercept the BOOT_COMPLETED intent and use that to re-register all alarms. This does unfortunately mean that for each alarm you have registered with the alarm manager you have to store it in your app's db as well.

So, you'll need a broadcast receiver to intercept the BOOT_COMPLETED intent:

public class BootReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // get your stored alarms from your database
        // reregister them with the alarm manager
    }
}

To get the BOOT_COMPLETED intent, you must put the following permission in your manifest:

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

And the BootReceiver also needs to be registered in your manifest with the following intent filter:

    <receiver android:enabled="true" android:name=".receiver.BootReceiver"
    android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
        <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </receiver>

It's important to note that if your app is installed to the sdcard, it can never receive the BOOT_COMPLETED intent. Also, it's worth noting that this implementation is a bit naive in that it executes code immediately on booting which can slow the user's phone down at startup. So, I recommend delaying your execution for a few minutes after intercepting the boot intent.

like image 139
danh32 Avatar answered Sep 30 '22 13:09

danh32


I personally would do it without a Broadcast Receiver. I'd get the AlarmManager to fire the intent to start a seperate Activity, rather than receiver. Then this new Activity could make the notification for you. I'm not sure if this is a better way, but it seems less complicated to me.

Edit: A Service would probably be better still than an Activity

In your MainActivity:

Intent i = new Intent(getBaseContext(), NotificationService.class);
PendingIntent pi = PendingIntent.getService(getBaseContext(), 0, i, 0);
AlarmManager mAlarm = (AlarmManager) Context.getSystemService(Context.ALARM_SERVICE);
mAlarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+10*60*1000, pi);

Your Service:

public class NotificationService extends Service {

public int onStartCommand(Intent intent, int flags, int startId) {   

//Create the notification here

return START_NOT_STICKY;
}

Your Manifest:

<service android:name="com.android.yourpath.NotificationService"></service>
like image 40
Matt Harris Avatar answered Sep 30 '22 11:09

Matt Harris