1

I have an app that should show a notification every 2 hours and should stop if user has already acted upon the notif. Since background services are history now, I thought of using WorkManager ("android.arch.work:work-runtime:1.0.0-beta01") for the same.

My problem is that although the work manager is successfully showing the notifications when app is running, but it won't show notification consistently in the following cases(I reduced the time span from 2 hours to 2 minutes to check the consistency):

  • when app is killed from the background.
  • device is in screen off.
  • state device is in unplugged state(i.e not charging).

By consistency , i mean that the notifications show at least once in the given time span. for 2 minutes time span, the freq of notifications went from once every 4 minutes to completely not show any notification at all. for 2 hours timespan( the timespan that i actually want), its been 4 hours and i haven't got a single notification. Here is the Code i am using for calling WorkManger:

    public class CurrentStreakActivity extends AppCompatActivity {
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...

        setDailyNotifier();
        ...
    }

    private void setDailyNotifier() {
        Constraints.Builder constraintsBuilder = new Constraints.Builder();
        constraintsBuilder.setRequiresBatteryNotLow(false);
        constraintsBuilder.setRequiredNetworkType(NetworkType.NOT_REQUIRED);
        constraintsBuilder.setRequiresCharging(false);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            constraintsBuilder.setRequiresDeviceIdle(false);
        }

        Constraints constraints =constraintsBuilder.build();


        PeriodicWorkRequest.Builder builder = new PeriodicWorkRequest
                .Builder(PeriodicNotifyWorker.class, 2, TimeUnit.HOURS);

        builder.setConstraints(constraints);
        WorkRequest request = builder.build();
        WorkManager.getInstance().enqueue(request);

    }
    ....
}

Here is the worker class(i can post showNotif(..) and setNotificationChannel(...) too if they might be erroronous):

public class PeriodicNotifyWorker extends Worker {
    private static final String TAG = "PeriodicNotifyWorker";

    public PeriodicNotifyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
        Log.e(TAG, "PeriodicNotifyWorker: constructor called" );
    }

    @NonNull
    @Override
    public Result doWork() {
//        Log.e(TAG, "doWork: called" );

        SharedPreferences sp =
                getApplicationContext().getSharedPreferences(Statics.SP_FILENAME, Context.MODE_PRIVATE);
        String lastcheckin = sp.getString(Statics.LAST_CHECKIN_DATE_str, Statics.getToday());
//        Log.e(TAG, "doWork: checking shared preferences for last checkin:"+lastcheckin );

        if (Statics.compareDateStrings(lastcheckin, Statics.getToday()) == -1) {
            Log.e(TAG, "doWork: last checkin is smaller than today's date, so calling creating notification" );
            return createNotificationWithButtons(sp);
        }
        else {
            Log.e(TAG, "doWork: last checkin is bigger than today's date, so no need for notif" );
            return Result.success();
        }
    }


    private Result createNotificationWithButtons(SharedPreferences sp) {
        NotificationManager manager =
                (NotificationManager) getApplicationContext().getSystemService((NOTIFICATION_SERVICE));
        String channel_ID = "100DaysOfCode_ID";
        if (manager != null) {
            setNotificationChannel(manager,channel_ID);
            showNotif(manager, channel_ID, sp);
            return Result.success();
        }
        else {
            return Result.failure();
        }

I am using a xiaomi miA2 androidOne device with Android Pie(SDK 28). There are a few other things that are troubling me:

  • What can i possibly do to know if my WorkManager is running? Other that just wait for 2 hours and hope for a notification. I actually tried something like that, keeping my phone connected to pc and checking android studio's logcat every now and then. It DOES run all the logs when the worker is actually called, but i don't think that's a correct way to test it, or is it?
  • In the above Code, the setDailyNotifier() is called from the onCreate() every time the app is opened. Isn't it Wrong? shouldn't there be some unique id for every WorkRequest and a check function like WorkManger.isRequestRunning(request.getID) which could let us check if a worker is already on the given task??If this was a case of AsyncTask, then boy we would have a mess.

I have also checked @commonsware's answer here about wakelock when screen is off, but i remember that work manager does use alarm manager in the inside when available. So what am I missing here?

2 Answers2

2

Few comments:
WorkManager has a minimum periodic interval of 15minutes and does not guarantee to execute your task at a precise time. You can read more about this on this blog.

All the usual background limitation you've on newer Android releases are still relevant when you use WorkManager to schedule your tasks. WorkManager guarantees that the task are executed even if the app is killed or the device is restated, but it cannot guarantee the exact execution.

There's one note about the tasks being rescheduled when your app is killed. Some OEM have done modification to the OS and the Launcher app that prevents WorkManager to be able to accomplish these functionality.

Here's the issuetracker discussion:

Yes, it's true even when the phone is a Chinese phone.
The only issue that we have come across is the case where some Chinese OEMs treat swipe to dismiss from Recents as a force stop. When that happens, WorkManager will reschedule all pending jobs, next time the app starts up. Given that this is a CDD violation, there is not much more that WorkManager can do given its a client library.

To add to this, if a device manufacturer has decided to modify stock Android to force-stop the app, WorkManager will stop working (as will JobScheduler, alarms, broadcast receivers, etc.). There is no way to work around this. Some device manufacturers do this, unfortunately, so in those cases WorkManager will stop working until the next time the app is launched.

Community
  • 1
  • 1
pfmaggi
  • 6,116
  • 22
  • 43
  • ```WorkManager has a minimum periodic interval of 15minutes and does not guarantee to execute your task at a precise time``` so what can be a way to test such module ? also can you please explain about this 15 mins minimum periodic interval? like what if user has to make a chat app that should check every 2 minutes from the server about a recieved message? –  Jan 07 '19 at 19:18
  • For you sample application, the best option would be to push a notification from the server instead of polling every x minutes for new messages. It's much better for the battery of the device. – pfmaggi Jan 08 '19 at 10:32
0

As of now , i have this app installed for last 8 days and i can confirm that the code is correct and app is working fine. as said by pfmaggi , the minimum time interval for work manager to schedule the work is 15 minutes, so there is a less chance that the WorkManager would have worked as expected in my testing conditions( of 2 minutes ) . Here are some of my other observations:

  • Like I said in the question that i was unable to recieve a notification for 4 hours even though i have passed the repeat interval as 2 hours. This was because of Flex Time. I passed in the flex time of 15 minutes and now it shows notifications between correct time interval. so i will be marking pfmaggi's answer as correct.
  • The problem of repeated work request can be solved by replacing WorkManager.getInstance().enqueue(request) with WorkManager.getInstance().enqueueUniqueWork(request,..)

  • I was still unable to find a way to test the work manager in the way i have described.

  • i have tested for every 15 minutes on android pie OnePlus phone but i notice its above 20 min now but the notification didnt showed after first time anybody know how to make periooidc mananger work – Sunil Chaudhary Aug 07 '19 at 11:08