0

I have a CalendarView that the user can touch and save school events. I would check every day at 15:00 PM check if in the database there are some events saved like homeworks and generate a notification of that.

What i need for do this?

  • AlarmManager
  • BroadcastReceiver (??)
  • Service

The AlarmManager manage the when start a Service, and in the Service i make the query that if it returns something i make the notification. I don't know if the BroadCastReceiver is needed.

It's all or i need something else? Can someone tell me how do that?

Activity that manage the when case:

public class MainActivity extends ActionBarActivity {

private PendingIntent pendingIntent;
private AlarmManager alarmManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set the alarm to start at approximately 2:00 p.m.
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 16);
    calendar.set(Calendar.MINUTE, 40);

    Intent myIntent = new Intent(MainActivity.this, MyBroadcastReceiver.class);
    pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);

    alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);

    // With setInexactRepeating(), you have to use one of the AlarmManager interval
    // constants--in this case, AlarmManager.INTERVAL_DAY.
    alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, pendingIntent);
}
}

My BroadcastReceiver

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent)
    {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "tag");

        //Acquire the lock
        wl.acquire();

        Log.v("ADebugTag", "It work!");

        int mId = 0;
        //Show the notification here.
        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(context)
                        .setSmallIcon(R.drawable.ic_action_edit)
                        .setContentTitle("Diario Scolastico")
                        .setContentText("Hai dei compiti da svolgere per domani!");
// Creates an explicit intent for an Activity in your app
        Intent resultIntent = new Intent(context, MainActivity.class);

// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
// Adds the back stack for the Intent (but not the Intent itself)
        stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
        stackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent =
                stackBuilder.getPendingIntent(
                        0,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );
        mBuilder.setContentIntent(resultPendingIntent);
        NotificationManager mNotificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
        mNotificationManager.notify(mId, mBuilder.build());


        //Release the lock
        wl.release();
    }

}

Manifest Permissions

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<receiver android:name=".MyBroadcastReceiver" />

Now i get notification but not in the established time and i don't know why!

Dario
  • 732
  • 7
  • 30

1 Answers1

0

The most appropriate use for your particular case would be the AlarmManager and a corresponding BroadcastReceiver as they were specifically created for situations like this. You don't need a service just for showing a notification.

Some problems that might lead to your issue that I saw by glancing at your code were:

alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);

should be:

//It's better to use the setInexactRepeating, but this is your call
int MILLIS_IN_A_DAY = 1000 * 60 * 60 * 24; //You can use an actual calculator so you don't have to compute it every time at runtime; also, lower it to something like 10000 ms to actually check if it is working
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), MILLIS_IN_A_DAY, pendingIntent);

Then you'd want to acquire the wakelock in your BroadcastReceiver onReceive method by doing so:

@Override
public void onReceive(Context context, Intent intent)
{
         PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

         PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 'YOUR TAG');

         //Acquire the lock
         wl.acquire();
         //You can show the notification here.

         //Release the lock
         wl.release();
 }

Also, don't forget to register the BroadcastReceiver in your AndroidManifest.xml

Alex Ionescu
  • 413
  • 6
  • 20
  • Thanks for your answer, so i don't need the service class? I can delete it? And show the notification in the Broadcast inside acquire() and release()? I will try! – Dario Dec 31 '15 at 12:55
  • `alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),0 , pendingIntent);` That method take 4 parameters, i put 0 but i don't know if it's right. – Dario Dec 31 '15 at 13:24
  • I was tired and did not check for the actual parameters. I've edited the answer with the correct params. Yes, you can delete the service. Good luck! – Alex Ionescu Dec 31 '15 at 18:25
  • No problem thanks but didn't work, the app don't show notification! I try with the app open and with the app close! But nothing happens... – Dario Jan 01 '16 at 20:12
  • I try with a Toas message inside acquire() and release() but nothing happens again, maybe the AlarmManager is not correct? – Dario Jan 02 '16 at 12:31
  • I will have a further look into it and actually build it and test it myself. – Alex Ionescu Jan 02 '16 at 16:12
  • Ok now it works, i don't understand when. Sometimes it works sometimes no. Now i test if work with screen locked, in the home and inside app! Thank you for the help! – Dario Jan 02 '16 at 16:51
  • It actually depends on the version of Android that you are testing. From android 5.0 I think it will trigger the wakelocks inexactly and group more of them so the device battery life should improve... Are you trying with setRepeating() method? – Alex Ionescu Jan 03 '16 at 15:28
  • I open a new discussion because it's a new problem, you can find (if you want) the discussion [link](http://stackoverflow.com/questions/34569262/android-alarmmanager-send-notification-every-time-app-starts-instead-of-only-onc/34569451?noredirect=1#comment56883461_34569451). Yes i'm trying all, setInexactRepeat() and setRepeat() but after the hour set the app show notifications every time that i start it! I hope to see you in the new discussion! Thanks! – Dario Jan 03 '16 at 15:45
  • Unfortunately I cannot comment on the new thread as I do not have enough reputation. As far as the alarm overwrite problem goes I'd suggest you to save the timestamp at which the alarm should trigger using the SharedPreferences and check every time you are setting a new alarm if that time is in the past or not. – Alex Ionescu Jan 04 '16 at 02:19