I have an app that generates data that needs to be sent to my server eventually (several hours of delay are no problem at all). I would like to do this with minimal impact to the user, which means to me:
- Minimal battery use
- No extra permissions, especially not "sketchy" ones
- No other strange changes to the system (see example later)
So far I've found three approaches, that all have some serious problems:
Using a SyncAdapter triggered by a network message:
Technically, this sounded like the perfect answer to the problem: Have the system call a service in my app whenever it's doing something on the network anyways. That way, the network is guaranteed to be available, there's barely any extra battery use, since the radio is already on, and the whole thing happens in the background...
And then I tried actually implementing it...
Unfortunately, this approach requires some weird modifications to the system: My app needs to create a new dummy account for the sync-process, even if my app doesn't otherwise use any accounts. And unfortunately, this account cannot be hidden from the user, so now my app is listed when the user clicks "Add Account" in the System Settings, but inside the app, there is no indication of user accounts anywhere... Also, I need to request all sorts of strange permissions, like "Create accounts and set passwords", "Toggle sync on and off", and "Read sync settings". Why would an app that doesn't even provide me with a user account require a permission to set passwords on my device??? Not cool... Delete!!!Using a BroadcastReceiver and checking for connectivity when it fires:
This requires permission to "view network connections" and possibly even "view information about Wi-Fi networking, such as whether Wi-Fi is enabled and names of connected Wi-Fi devices" ... Why would this app care about my wi-fi or network neighborhood? Creepy... Not getting installed on my device...
The nice thing about this approach is that a network connectivity change likely only happens while the radios are turned on (at least a change to the "available" state). So, if I use this event to trigger an upload (attempt), the battery-impact will be minimal as I won't cause the radio to turn on just for the upload. Unfortunately, this event will probably not be called very often. And to make matters worse, from the docs it sounds like the BroadcastReceiver will only be called while my app is in the resumed-state. So, I won't even be able to make use of events while my app is paused... I.e. using these broadcast events will only be slightly better than option 3:Just blindly initiating the upload at regular intervals and, if it fails, retrying it again later:
This approach doesn't require any strange permissions and doesn't mess with any system settings. But, clearly, it is the worst I can do for battery use. So, while it's workable, I'd rather find a smarter alternative...
Is there a way to fix the issues of one of the first two approaches? The optimal solution would be a SyncAdapter without a dummy user-account, or, at least, with a hidden one, or one that already exists in the system... But many hours of searching didn't yield any usable answers...
Or is there another better way altogether?