Notification at 0h00 without starting application

Asked

Viewed 782 times

7

I would like to notify the user that he has an expense that expires the next day, but without the need for the application to be running, currently I have a code that notifies from the moment I enter the application, I would like to do it (no user interaction) notify 0h00 every day in case you have any expenses due the next day.

Code I already have

Loginactivity - onCreate method

 Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 1);
    calendar.set(Calendar.AM_PM, Calendar.AM);
    Intent myIntent = new Intent(this, MyReceiver.class);
    pendingIntent = PendingIntent.getBroadcast(this, 0, myIntent, 0);
    AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
    alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntent);

Receiver

public class MyReceiver extends BroadcastReceiver {
    public MyReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Intent service1 = new Intent(context, MyService.class);
        context.startService(service1);
    }
}

Service

public class MyService extends Service {
    private NotificationManager mManager;

    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @SuppressWarnings("static-access")
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Calendar calendar = Calendar.getInstance();
        DespesaDAO DAO = new DespesaDAO(getApplicationContext());
        List<Despesa> list = DAO.getAllVencidasAmanha(calendar);
        if (list.size() > 0) {
            mManager = (NotificationManager) this.getApplicationContext().getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
            Intent intent1 = new Intent(this.getApplicationContext(), LoginActivity.class);
            Notification notification = new Notification(R.drawable.ic_launcher, "Existem "+list.size()+" despesas que vencerão amanhã!", System.currentTimeMillis());
            intent1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this.getApplicationContext(), 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
            notification.setLatestEventInfo(this.getApplicationContext(), String.valueOf(list.size()) + " despesas vencem amanhã", "Fique alerta para não se endividar!", pendingNotificationIntent);
            mManager.notify(0, notification);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
  • Without the application running? Maybe through a push notification, but then you will depend on Internet.

  • Notify him how? email? mobile? popup?

  • Notification @Intruder, those that stay in the statusbar

1 answer

6

The solution is to set the alarm that will launch the service that generates the notification at the start of the device.

This service must be performed every day at 0.00.

To this end, please note Androidmanifest.xml, a Broadcastreceiver who responds to action android.intent.action.BOOT_COMPLETED:

<receiver android:name="aSuaPackage.StartUpBootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>  

Add this permission:

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

In that Broadcastreceiver set the alarm:

public class StartUpBootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {

            // Cria um Calendar para as 0 horas do dia seguinte
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(System.currentTimeMillis());
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            calendar.set(Calendar.HOUR_OF_DAY, 0);

            //PendingIntent para lançar o serviço
            Intent serviceIntent = new Intent(context, MyService.class);
            PendingIntent pendingIntent = PendingIntent.getService(context, 0, serviceIntent, 0);

            //Alarme que se repete todos os dias às 0 horas
            AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);

            alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
                                calendar.getTimeInMillis(),
                                AlarmManager.INTERVAL_DAY,
                                pendingIntent);

        }
    }
}  

The service should check if there is a payment to be made and, if yes, launch the notification.

Notes

  • It is necessary to execute the application once before it can respond to android.intent.action.BOOT_COMPLETED action. The same applies if your execution has been stopped using Force Close.
  • The application needs to be installed in the cellular memory.
  • The use of Startupbootreceiver is necessary to ensure that the alarm is reset when the device is switched off and then on.
  • setInexactRepeating() does not guarantee that the alarm will be triggered at exactly the right time. As this is not relevant in this case, its use is advised to be more resource-efficient. If it were to be used setRepeating()
  • In the first time that the application is executed must set the alarm, if it does not do it it will only be set when the device disconnect and connect.

See this reply for a more complete implementation.

  • What would be the best way to take the test? Because the notification will only ring when you have an expense due the next day, that is, the application will already have run its first time, or am I wrong? @ramaral

  • Have the service display a Toast that indicates it has been executed, set the alarm to in 5 minutes, turn off and turn on the device if Toast is shown is because it works. If you did everything right, I guarantee it works.

  • I have a question, if I install the app now on my phone, I need to restart the device for notifications to work? The five-minute test worked.

  • Yes if you don’t do as I said on the last note.

  • How do I set this alarm the first time I run the app? @ramaral

  • 1

    Adapt the code of this reply. The answer shows how to execute code only the first time you open the application. The code to execute is the same as the one in Broadcastreceiver

  • Have you been able to implement? Have more questions?

  • I implemented, but it does not play 0h00, plays a few minutes after the app starts @ramaral

  • This is the normal behavior of Alarmmanager when the set date/time is in the past. In the Calendar setting add calendar.add(Calendar.DAY_OF_MONTH, 1); after the line calendar.setTimeInMillis(System.currentTimeMillis());

  • What is the purpose of this line? @ramaral

  • calendar.setTimeInMillis(System.currentTimeMillis()); sets the Calendar for the current time and day, as if you want the alarm to be activated the next day add a day with calendar.add(Calendar.DAY_OF_MONTH, 1);

  • You use new Intent(context, MyService.class); So besides Broadcastreceive, it is necessary to create a class for the service? How would you set exactly this time: 19:30:12hr for daily notifications?

  • In what method would I launch my notification?!

  • Broadcastreceiver serves to define the Alarmmanager that will launch a service at the set time. The service, type Intentservice, will launch the notification in the method onHandleIntent()

Show 9 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.