2

I need a periodic task that require internet connection and persists after reboots. I have achieved that much but the problem is that I want the app to continue working even adter I exit it.

As in, if I exist the app and turn off wifi and then turn it back again (and if the period is up) then the task should be triggered and work in the background.

This is the startPeriodicTask method

   public void startPeriodicTask() {
        Log.d(TAG, "startPeriodicTask");

        // [START start_periodic_task]
        PeriodicTask task = new PeriodicTask.Builder()
                .setService(MyTaskService.class)
                .setTag(TASK_TAG_PERIODIC)
                .setPeriod(30L)
                .setPersisted(true) // to persist after reboot
                .setRequiredNetwork(Task.NETWORK_STATE_ANY ) 
                .build();

        mGcmNetworkManager.schedule(task);
        // [END start_periodic_task]
    }

and I just call this method in the OnCreate right after checking for playServices

checkPlayServicesAvailable();
startPeriodicTask();

I've added this to manifest in order for the job to persist after reboot

<uses-permission android:name="android.Manifest.permission.RECEIVE_BOOT_COMPLETED" />
student93
  • 307
  • 2
  • 12
  • Where are you calling startPeriodicTask()? Is it in an Activity, Service, Receiver? – Michael Vescovo Feb 26 '17 at 18:47
  • @MichaelVescovo I'm calling startPeriodicTask() in the activity, specifically in the OnCreate as I've already written in my original post. then, ` PeriodicTask task = new PeriodicTask.Builder() .setService(MyTaskService.class)` calls the service MyTaskService which has the method onRunTask() that will be executed when the conditions are met (there is an available network and the period is up). This works perfectly as long as the activity is in the foreground but if I exit it no longer works. – student93 Feb 26 '17 at 19:05
  • I need this to work in the background without any intervention from the user aside from initially installing the app. I need this to work in the background without any intervention from the user aside from initially installing the app. – student93 Feb 26 '17 at 19:06

1 Answers1

0

The only way to have a task start again after the wifi comes back on is to call it from a Receiver. So you need to create a receiver that gets called when the network state changes. Then inside this you can check if it's on or off. If it's on, then call your method.

You can see exactly how to do this in the sample at the bottom of this documentation page: https://developer.android.com/training/basics/network-ops/managing.html

Michael Vescovo
  • 3,741
  • 4
  • 32
  • 45
  • 1
    but isn't that no longer available starting from api marshmallow ? I mean declaring an intent that is based on network changed state. I thought this is no longer an option starting from api23 and that is why I tried using jobscheduler but it is limited to api>=21 and that brought me to gcm because it works on much lower api with a similar mechanism to jobscheduler. – student93 Feb 26 '17 at 19:08
  • No I don't know where you got that from. It works for all versions as far as I know. I've used this myself in Marshmellow and up and it works fine. I've also used it below Marshmellow and it also works. – Michael Vescovo Feb 26 '17 at 19:43
  • If you want to quickly test that it works you can implement this little notification I built from that code. It will tell you when the wifi is on or off as it happens. https://github.com/mvescovo/utils/tree/master/network But when you create your own version you need to declare it in the manifest not the Activity so that it runs no matter what (in the background). Just have it start a service that runs your code. That's it. It shouldn't take too long. – Michael Vescovo Feb 26 '17 at 19:49
  • 2
    my mistake. I meant Nougat not marshmallow. As it says in the official docs. "Apps targeting Android 7.0 (API level 24) and higher do not receive CONNECTIVITY_ACTION broadcasts if they declare the broadcast receiver in their manifest. Apps will still receive CONNECTIVITY_ACTION broadcasts if they register their BroadcastReceiver with Context.registerReceiver() and that context is still valid." – student93 Feb 26 '17 at 19:51
  • 2
    this is why I can't use that solution because I need to target api>=24 as well as the ones before that (probably going back to api14) and this is why I'm using GcmNetworkManager because it works on api>=14, only drawback is that it requires google play services. – student93 Feb 26 '17 at 19:56
  • Oh I didn't know about that. Well in that case it might be better to use a JobScheduler if you don't need GcmNetworkManager. https://developer.android.com/topic/performance/background-optimization.html – Michael Vescovo Feb 26 '17 at 20:06
  • you see, there's another issue with job scheduler. I want the task to be periodic but also have a connectivity requirement. If I use both set periodic and set network requirement, jobscheduler automatically ignores the network requirement and schedules the job to run after the period is up. That is what made me choose GcmNetworkManager. It meets the requirements perfectly as long as the main activity is running in the foregound but I can't seem to find a way to make the task run even after exiting the app. – student93 Feb 26 '17 at 20:12
  • 1
    another advantage of GcmNetworkManager is that is does use job scheduler when it's available but for lower api is uses a sort of moch job scheduler which makes the same code work on even lower api without having to write different codes for lower api – student93 Feb 26 '17 at 20:13
  • So if it works but only when the app is running, maybe try starting it outside the app. Like maybe at boot up from the "SampleBootReceiver" here https://developer.android.com/training/scheduling/alarms.html – Michael Vescovo Feb 26 '17 at 20:28
  • Then if you can get that to work, you could toggle behaviour by setting a flag in sharedPreferences. So If you enable/disable it from the app, the code in the boot receiver will only start it if it's enabled. – Michael Vescovo Feb 26 '17 at 20:30
  • When I say outside the app I mean outside the running app. Of course it's still part of the app. – Michael Vescovo Feb 26 '17 at 20:32
  • thank you for the suggestion, I'll make sure to try this. – student93 Feb 26 '17 at 20:34