3

My app requires that a notification be sent twice a day. For testing purposes, I have shortened this time to 1 hour. This, of course, must be done in the background/when app is closed, so I have already tried AlarmManager and that did not work. I have therefore switched to WorkManager. someone suggested that I use periodicWork to accomplish my task but here is the issue: WorkManager only executes all periodic work when the app is open Another weird thing: If I leave the app alone for 3 hours, I will get way more than three notifications when I open the app.

I know for a fact that WorkManager is not executing because I have instantiated a Date Object whenever doWork() is called, and that timestamp from the date object is printed to the notification. This printed time will ALWAYS show as the time I have opened the app, meaning all of the queued work requests were executed at once when I opened the app.

Here is what is used to set the alarm. Note that cancelAlarm() does not cancel the alarm, but rather resets a shared preference I used for debugging

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_enter);
        ToggleButton toggle = findViewById(R.id.toggleButton);
        toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if(isChecked) {
                    setAlarm();
                } else {
                    cancelAlarm();
                }
            }
        });
    }

    private void setAlarm() {
        Constraints constraints = Constraints.NONE;
        PeriodicWorkRequest testRequest = new PeriodicWorkRequest.Builder(ReminderWorker.class, 1, TimeUnit.HOURS)
                .setConstraints(constraints)
                .build();
        WorkManager.getInstance().enqueueUniquePeriodicWork("ReminderWork", ExistingPeriodicWorkPolicy.KEEP, testRequest);
    }

    private void cancelAlarm() {
        SharedPreferences savedSharedPreferences = getApplicationContext().getSharedPreferences("USER_PREFERENCES", Context.MODE_PRIVATE);
        final SharedPreferences.Editor editor = savedSharedPreferences.edit();
        editor.putInt("Test", 0);
        editor.commit();
    }

Here is the actual ReminderWorker class, I put a SHaredPreference variable to check the amount of times the worker fired, and a Date objectto check the time fired. These are printed in the notification.

public class ReminderWorker extends Worker {
    int i;
    public final String CHANNEL_ID = "MainChannel";
    public ReminderWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
    }



    @NonNull
    @Override
    public Result doWork() {
        Date date = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        SharedPreferences savedSharedPreferences = getApplicationContext().getSharedPreferences("USER_PREFERENCES", Context.MODE_PRIVATE);
        final SharedPreferences.Editor editor = savedSharedPreferences.edit();
        i = savedSharedPreferences.getInt("Test", 0) + 1;
        editor.putInt("Test", i);
        editor.commit();
        createNotificationChannel();
        buildNotification(cal);
        return Result.success();
    }
    private void createNotificationChannel() {
        String name = "Birthday Notifications";
        String description = "Reminds you when your friends birthday approaches";
        int importance = NotificationManager.IMPORTANCE_HIGH;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        NotificationManager notificationManager = getApplicationContext().getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
    private void buildNotification(Calendar cal) {
        Context context = getApplicationContext();
        Intent openTap = new Intent(context, EnterActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, openTap, 0);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID);
        builder.setSmallIcon(R.drawable.pix_cake);
        builder.setContentTitle("TestNotification");
        builder.setStyle(new NotificationCompat.BigTextStyle()
                .bigText("TestText" + i + " Time: " + cal.get(Calendar.HOUR) + ":" + cal.get(Calendar.MINUTE)));
        builder.setPriority(NotificationCompat.PRIORITY_MAX);
        builder.setContentIntent(pendingIntent);
        builder.setAutoCancel(true);

        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
        notificationManager.notify(i, builder.build());
        //notificationManager.cancelAll();
    }
}

In case it is needed, here is my AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myfirstapp">

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.SET_ALARM" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/main_icon"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/main_icon_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".ListOfDaysActivity" />
        <activity android:name=".MainActivity" />
        <activity android:name=".EnterActivity"
            android:launchMode="singleInstance">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

No errors thrown, just not the result expected. I need a notification to show up roughly every hour but that simply isn't happening.Any way around this?

1 Answers1

0

Do you remove the application from task manager? Which device are you using for testing? There are some devices that force close the app and WorkManager tasks are rescheduled once you open the app again. This answer might help you understand what is going on - https://stackoverflow.com/a/52605503/1313699

Branislav Kuliha
  • 149
  • 2
  • 10