Android Project notifies after 5 minutes if the device screen is off / Doze/ Sleep Mode

Viewed 34

I saw this open source project on github. But it has an issue for me on not notifying exact set schedule if the screen is off. I want to re-program it to notify on the exact time set by the user even the device screen is off.

Question: "Android Project notifies after 5 minutes if the device screen is off / Doze/ Sleep Mode."

Note: Target SDKversion 23 - 33

MainActivity.java

public class MainActivity extends AppCompatActivity {

public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
private static final String TAG = "MainActivity";


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


}

//Schedule alarm notification
private void scheduleNotification(Notification notification, long delay) {
   

    Intent notificationIntent = new Intent(this, MyNotificationPublisher.class);
    notificationIntent.putExtra(MyNotificationPublisher.NOTIFICATION_ID, 1);
    notificationIntent.putExtra(MyNotificationPublisher.NOTIFICATION, notification);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    assert alarmManager != null;
    alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, delay, pendingIntent);
    Log.d(TAG, "scheduleNotification: Notification set successfully!");
}

//Build notification
private Notification getNotification(String content) {
    //on notification click open MainActivity
    Intent intent = new Intent(this, MainActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, default_notification_channel_id);
    builder.setContentTitle("ToDo Reminder");
    builder.setContentText(content);
    builder.setContentIntent(pendingIntent);
    builder.setAutoCancel(true);
    builder.setSmallIcon(R.drawable.ic_stat_name);
    builder.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND);
    builder.setChannelId(NOTIFICATION_CHANNEL_ID);
    builder.setPriority(NotificationCompat.PRIORITY_HIGH);
    return builder.build();
}
final Calendar cal = Calendar.getInstance();
    cal.setTimeInMillis(System.currentTimeMillis());

    //Set custom date
    dateText.setOnClickListener(new View.OnClickListener() {
        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        public void onClick(View v) {
            final DatePickerDialog datePickerDialog = new DatePickerDialog(MainActivity.this,
                    new DatePickerDialog.OnDateSetListener() {
                        @Override
                        public void onDateSet(DatePicker view, int year,
                                              int monthOfYear, int dayOfMonth) {
                            String newMonth = getMonth(monthOfYear + 1);
                            dateText.setText(dayOfMonth + " " + newMonth);
                            cal.set(Calendar.YEAR, year);
                            cal.set(Calendar.MONTH, monthOfYear);
                            cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
                            Log.d(TAG, "onDateSet: Date has been set successfully");
                        }
                    }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH));
            datePickerDialog.show();
            datePickerDialog.getDatePicker().setMinDate(date);
        }
    });


    //Set custom time
    timeText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            TimePickerDialog timePickerDialog = new TimePickerDialog(MainActivity.this,
                    new TimePickerDialog.OnTimeSetListener() {
                        @Override
                        public void onTimeSet(TimePicker view, int hourOfDay,
                                              int minute) {
                            String time;
                            String minTime = String.format("%02d", minute); //prefix zero to minute if its single digit
                            //Method to postfix AM/PM
                            if (hourOfDay >= 0 && hourOfDay < 12) {
                                time = hourOfDay + " : " + minTime + " AM";
                            } else {
                                if (hourOfDay != 12) {
                                    hourOfDay = hourOfDay - 12;
                                }
                                time = hourOfDay + " : " + minTime + " PM";
                            }

                            timeText.setText(time);
                            cal.set(Calendar.HOUR, hourOfDay);
                            cal.set(Calendar.MINUTE, minute);
                            cal.set(Calendar.SECOND, 0);
                            Log.d(TAG, "onTimeSet: Time has been set successfully");
                        }
                    }, cal.get(Calendar.HOUR), cal.get(MINUTE), false);
            timePickerDialog.show();
        }
    });


    dialogBuilder.setTitle("Lets add new task!");
    dialogBuilder.setPositiveButton("Done", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            String title = editTitle.getText().toString();
            String date = dateText.getText().toString();
            String time = timeText.getText().toString();
            if (title.length() != 0) {
                try {
                    insertDataToDb(title, date, time);
                    scheduleNotification(getNotification(title), cal.getTimeInMillis());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                toastMsg("Oops, Cannot set an empty ToDo!!!");
            }
        }
    });
    dialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            //pass
            dialog.cancel();
        }
    });
}

MyNotificationPublisher.java

public class MyNotificationPublisher extends BroadcastReceiver {

public static String NOTIFICATION_ID = "notification-id";
public static String NOTIFICATION = "notification";

public void onReceive(Context context, Intent intent) {
    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    Notification notification = intent.getParcelableExtra(NOTIFICATION);

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        int importance = NotificationManager.IMPORTANCE_HIGH;
        NotificationChannel notificationChannel = new NotificationChannel(MainActivity.NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance);
        assert notificationManager != null;
        notificationManager.createNotificationChannel(notificationChannel);
    }
    int id = intent.getIntExtra(NOTIFICATION_ID, 0);
    assert notificationManager != null;
    notificationManager.notify(id, notification);
}
}

Inside of Manifest File

<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

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

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

    <receiver android:name=".MyNotificationPublisher" />
</application>
0 Answers
Related