user9955789
user9955789

Reputation:

How to receive a daily notification at a specific time in Android with WorkManager and OneTimeWorkRequest?

My goal

Receive a single notification every 8 am when my switch is activated

Current result

-I receive a notification each time I launch the app if I first activated the switch

-I also receive notifications without launching the app at any time

-In addition, I receive several notifications in one day

what I did (my code)

-NotificationActivity (part of the onCreate)

 private void onClickSwitch() {
        aSwitch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                retrieveKeyWord();
                retrieveCategories();

                keywordPref = mPreferences.getString(PREF_KEYWORD, null);
                categoriesPref = mPreferences.getString(PREF_CATEGORIES, null);

                mPreferences.edit().putString(PREF_KEYWORD, keyword).apply();
                mPreferences.edit().putString(PREF_CATEGORIES, categories).apply();

                Calendar currentDate = Calendar.getInstance();
                Calendar dueDate = Calendar.getInstance();

                dueDate.set(Calendar.HOUR_OF_DAY, 8);
                dueDate.set(Calendar.MINUTE, 0);
                dueDate.set(Calendar.SECOND, 0);

                if(dueDate.before(currentDate)) {
                    dueDate.add(Calendar.HOUR_OF_DAY, 24);
                }

                long timeDiff =  dueDate.getTimeInMillis() - currentDate.getTimeInMillis();


                Constraints constraints = new Constraints.Builder()
                        .setRequiredNetworkType(NetworkType.CONNECTED)
                        .build();

                OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(NotificationWorker.class).setInitialDelay(timeDiff, TimeUnit.MILLISECONDS)
                        .setConstraints(constraints)
                        .addTag("TAG_OUTPUT").build();


                WorkManager.getInstance().enqueue(oneTimeWorkRequest);

            }
        });
    }

-NotificationActivity -> Layout

layout

-NotificationWorker

public class NotificationWorker extends Worker {

    private SharedPreferences mPreference;
    private String keyword;
    private String categories;
    private ResultModel resultModel;
    private ResultContract.Model.OnFinishedListener onFinishedListener;
    private int numberOfArticle;


    public NotificationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {

        mPreference = getApplicationContext().getSharedPreferences(NotificationActivity.PREFERENCE_FILE, MODE_PRIVATE);

        keyword = mPreference.getString(NotificationActivity.PREF_KEYWORD, null);
        categories = mPreference.getString(NotificationActivity.PREF_CATEGORIES, null);


        resultModel = new ResultModel();

        numberOfArticle = resultModel.getResultListWithoutDate(onFinishedListener, 1, keyword, categories);

        displayNotification(keyword);

        return Result.success();
    }


    private void displayNotification(String keyword) {

     NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);

     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
         NotificationChannel channel = new NotificationChannel("simplifiedcoding", "simplifiedcoding", NotificationManager.IMPORTANCE_DEFAULT);
         assert notificationManager != null;
         notificationManager.createNotificationChannel(channel);
     }

     NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), "simplifiedcoding")
             .setContentTitle("Articles sur : " + keyword)
             .setContentText("Nombre d'articles trouvés : " + numberOfArticle)
             .setPriority(NotificationCompat.PRIORITY_DEFAULT)
             .setSmallIcon(R.drawable.ic_launcher_background);

        assert notificationManager != null;
        notificationManager.notify(1, builder.build());

    }
}

Tell me if you need more information, thanks to who will help me

Upvotes: 2

Views: 2627

Answers (3)

Niklas
Niklas

Reputation: 25413

This does work when using PeriodicWorkRequest. The trick is to use setInitialDelay.

fun Context.enqueueReminderWorker(
  localTime: LocalTime
) {
  val now = ZonedDateTime.now()
  val trigger = now.with(localTime)
  val realTrigger = when {
    trigger <= now -> trigger.plusDays(1)
    else -> trigger
  }

  val initialDelay = maxOf(1, realTrigger.toEpochSecond() - Instant.now().epochSecond)

  val notificationWork = PeriodicWorkRequest.Builder(NotificationWorker::class.java, 1, DAYS)
    .setInitialDelay(initialDelay, SECONDS)
    .build()

  WorkManager.getInstance(this)
    .enqueueUniquePeriodicWork(NotificationWorker.TAG, ExistingPeriodicWorkPolicy.REPLACE, notificationWork)
}

I'll have a PeriodicWorkRequest with an interval of 1 Day (24 hours) and using setInitialDelay I can shift the starting time from now to my desired starting point e.g. 8 AM in the morning. NotificationWorker is as simple as:

class NotificationWorker(
  context: Context,
  workerParams: WorkerParameters
) : Worker(context, workerParams) {
  override fun doWork(): Result {
    // Your logic to show a notification.

    return Result.success()
  }

  companion object {
    const val TAG = "DailyReminder"
  }
}

I'm calling Context#enqueueReminderWorker in Application#onCreate and when the user changes the preferred time.

Upvotes: 1

Muhammad Awais
Muhammad Awais

Reputation: 548

As your goal is to receive notification everyday at 8 am, I would recommend you to use PeriodicWorkRequest rather than using OneTimeWorkRequest.

PeriodicWorkRequest (From Documentation):

A WorkRequest for repeating work. This work executes multiple times until it is cancelled, with the first execution happening immediately or as soon as the given Constraints are met. The next execution will happen during the period interval; note that execution may be delayed because WorkManager is subject to OS battery optimizations, such as doze mode.

OneTimeWorkRequest (From Documentation):

A WorkRequest for non-repeating work.

Upvotes: 1

alireza daryani
alireza daryani

Reputation: 835

You can solve it with 3 ways.

First:

User Alarm Manager and put that in a IF that check activity is alive so it will work if your app opened.you can take more Information from google docs link below:

AlarmManager Docs

Second :

u can Use a Timer with Task to create a notification, you can check if activity alive again but better use is that to create Timer on Foreground service.

Third:

Use PushNotification from server when even u need it. the Docs and information if link below:

Push Notification - One Signal

Note:

I recommend You to use third way for your issue.

Have good Coding and dont forget vote me ;)

Upvotes: 2

Related Questions