Reputation:
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
-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
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
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
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:
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