25

Hi I am working on application where I have set the notification on user entered date and time through background service. Now I want to set notification/alarm daily at 6 pm to ask user does he want to add another entry? How can I achieve this? Should I use the same background service or Broadcast receiver? Please give me better solution for that and tutorial will be great idea. Thanks in advance.

user3458918
  • 827
  • 1
  • 10
  • 15
  • This answer can solve your problems https://stackoverflow.com/questions/63471520/send-daily-notification-at-a-scheduled-time-android/68936552#68936552 – Yaqoob Bhatti Aug 26 '21 at 10:11

3 Answers3

62

First set the Alarm Manager as below

 Calendar calendar = Calendar.getInstance();
 calendar.set(Calendar.HOUR_OF_DAY, 18);
 calendar.set(Calendar.MINUTE, 30);
 calendar.set(Calendar.SECOND, 0);
 Intent intent1 = new Intent(MainActivity.this, AlarmReceiver.class);
 PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0,intent1, PendingIntent.FLAG_UPDATE_CURRENT);
 AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
 am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);

Create an Broadcast Receiver Class "AlarmReceiver" in this raise the notifications when onReceive

public class AlarmReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub

        long when = System.currentTimeMillis();
        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);

        Intent notificationIntent = new Intent(context, EVentsPerform.class);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
                notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);


        Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(
                context).setSmallIcon(R.drawable.applogo)
                .setContentTitle("Alarm Fired")
                .setContentText("Events to be Performed").setSound(alarmSound)
                .setAutoCancel(true).setWhen(when)
                .setContentIntent(pendingIntent)
                .setVibrate(new long[]{1000, 1000, 1000, 1000, 1000});
        notificationManager.notify(MID, mNotifyBuilder.build());
        MID++;

    }

}

and in the manifest file, register receiver for the AlarmReceiver class:

<receiver android:name=".AlarmReceiver"/>

No special permissions are required to raise events via alarm manager.

Athena
  • 302
  • 4
  • 16
Mr. N.V.Rao
  • 1,082
  • 13
  • 27
  • mid is int datatype for notification id. Declare the variable in class level variable. – Mr. N.V.Rao Jun 08 '15 at 05:45
  • 1
    What does MID do? What is its significance? – Srujan Barai Aug 24 '15 at 11:48
  • 7
    @N.V.Rao `` is not required. It is used to set alarm in device's alarm clock. – Mehul Joisar Aug 25 '15 at 13:11
  • @SrujanBarai: mid is nothing but notification id of integer type. it should be unique for each notification. – Mehul Joisar Aug 25 '15 at 13:12
  • @MehulJoisar Will Notification overright if MID is same? – Srujan Barai Aug 25 '15 at 13:14
  • 1
    @SrujanBarai : yes. It will be override. – Mehul Joisar Aug 25 '15 at 13:26
  • 13
    I would add `if(calendar.getTime().compareTo(new Date()) < 0) calendar.add(Calendar.DAY_OF_MONTH, 1);` to the calendar initialization to avoid an immediate notification if the time you set has already passed "today". – Daniel López Lacalle Jan 29 '16 at 15:39
  • Should MID be a static variable? – Mateus Viccari Jul 04 '16 at 18:13
  • i know this is an older question...but i implemented the code above, and it works great...the only thing is that the notification just keeps popping up over and over again after i clear it or click on it. I'm not sure how to prevent this from happening. Any suggestions? – SillyFidget Jul 06 '16 at 15:47
  • mid is nothing but notification id of integer type. it should be unique for each notification. @MateusViccari – Mr. N.V.Rao Jul 07 '16 at 03:56
  • 3
    @N.V.Rao Thanks, for anyone else looking for best practices on setting the notification ID, check the answer to this question: http://stackoverflow.com/questions/25713157/generate-int-unique-id-as-android-notification-id – Mateus Viccari Jul 07 '16 at 11:44
  • 3
    Since API 19, `setRepeating` in the AlarmManager is inexact (see https://developer.android.com/reference/android/app/AlarmManager.html). You should use `setExact` (API 19-22) or `setExactAndAllowWhileIdle` (API 23+). Note that this is a one time only alarm, so you have to set the alarm again when you receive an alarm in `onReceived()` of the AlarmReceiver. – Lukas Lechner Jul 21 '16 at 10:47
  • Will this popsup daily? – Cyph3rCod3r Sep 29 '16 at 08:06
  • 1
    What if I want to execute this at 12PM once and again at 6PM? – Si8 Nov 25 '16 at 16:17
  • @Daniel Lopez where would i add that? – Si8 Nov 27 '16 at 04:15
  • @Si8 Just after `calendar.set(Calendar.SECOND, 0);` – Daniel López Lacalle Nov 28 '16 at 09:20
  • 1
    It keeps repeating every time I open the when when the time is past the alarm time. Any idea how to display it once at 12 and once at 6? – Si8 Nov 28 '16 at 21:14
  • 1
    Warning: Put the `receiver` tag inside the `application` tag in AndroidManifest.xml file. It took a lot of time from me... – Amiraslan Jun 14 '17 at 16:09
  • 1
    its not working for me when app is not running in background – Lavanya Velusamy Dec 05 '17 at 10:59
  • instead of using "am.setRepeating" use "am.setInexactRepeating" as per Google Documentation. – Ali Akram Aug 30 '18 at 17:08
  • 3
    what is "EVentsPerform" class? – roghayeh hosseini Jan 05 '19 at 14:45
  • 1
    @LukasLechner setExactAndAllowWhileIdle (API 23+). Note that this is a one time only alarm, so you have to set the alarm again when you receive an alarm in onReceived() of the AlarmReceiver -- How can i achieve this??? – Prajwal Waingankar Mar 23 '20 at 10:22
  • Note that from API 23 on you also need to [ask for ignoring battery optimization](https://developer.android.com/training/monitoring-device-state/doze-standby.html#support_for_other_use_cases), otherwise the alarm won't fire. – user905686 Apr 15 '21 at 13:44
4

N.V.Rao's answer is correct, but don't forget to put the receiver tag inside the application tag in the AndroidManifest.xml file:

<receiver android:name=".alarm.AlarmReceiver" />
tommy
  • 41
  • 3
  • 1
    Thanks for pointing out. Instead of adding this as a separate answer, you could have edited @Mr. N.V.Rao 's answer – Kathir Sep 09 '20 at 15:16
2

Year 2021, April
This is a sample code for Daily Repeating Notification On Specific Time(Here 8AM) in Android:-
1. MainActivity.class

package com.manab.notificationx;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import java.util.Calendar;


public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super .onCreate(savedInstanceState) ;
        setContentView(R.layout.activity_main ) ;

    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 08);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    if (calendar.getTime().compareTo(new Date()) < 0) calendar.add(Calendar.HOUR_OF_DAY, 0);
    Intent intent = new Intent(getApplicationContext(), NotificationReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    if (alarmManager != null) {
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
    }
    }


}    

AlarmReceiver.class // This is a broadcast Receiver which is needed for background process

package com.manab.notificationx;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;

public class AlarmReceiver extends BroadcastReceiver {
    private static final String CHANNEL_ID = "this.is.my.channelId";//you can add any id you want
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent notificationIntent = new Intent(context, NotificationActivity.class);//on tap this activity will open

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
        stackBuilder.addParentStack(NotificationActivity.class);
        stackBuilder.addNextIntent(notificationIntent);

        PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);//getting the pendingIntent

        Notification.Builder builder = new Notification.Builder(context);//building the notification

        Notification notification = builder.setContentTitle("Demo App Notification")
                .setContentText("New Notification From Demo App..")
                .setTicker("New Message Alert!")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentIntent(pendingIntent).build();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder.setChannelId(CHANNEL_ID);
        }

        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
//below creating notification channel, because of androids latest update, O is Oreo
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(
                    CHANNEL_ID,
                    "NotificationDemo",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            notificationManager.createNotificationChannel(channel);
        }

        notificationManager.notify(0, notification);
    }
}

NotificationActivity.class //Remember this is an activity, not a class, so create an empty activity.

package com.manab.notificationx;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class NotificationActivity extends AppCompatActivity {

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

AndroidManifest.xml // Just add the indicated line below

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.manab.notificationx">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.NotificationX">
        <activity android:name=".NotificationActivity"></activity>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <receiver android:name=".AlarmReceiver" />//copy only this line of code
    </application>

</manifest>

Let me know if it's working or not

Ar3max
  • 29
  • 1
  • 3