Beeminder Forum

Android TagTime build or build instructions for latest update


#1

I see there have been some updates to the TagTime code this year.

But it looks like the most recent Android app is several years old.

Is there an updated build available? It looks like people are using the recent changes so there should be a build somewhere.

Or is it something I need to compile and build with ADK? If so, are there instructions somewhere to help with this?


#2

I hope all the instructions we have are in the repo. I believe @chrp is the last one to have gotten a build working, as discussed here:

That would be wonderful if you can get a build built!


#3

There have been changes more recently than that - about 4 months ago you did some “light exorcising” and merged a branch: https://github.com/tagtime/TagTime


#4

Yay got it to run!

The APK is here if anyone wants it:
https://www.mediafire.com/file/s7473wn72pm93ds/tagTime-debug.apk/file

Ideally the one in the app store should be updated with this latest version.

(It’s in src\and\tagTime\build\outputs\apk\debug after building - there’s a “Build APK” menu option under the Build menu)


#5

In order to update the Play Store, the APK will need to be signed with the same keys.


#6

Important thing that it took me 6 months to figure out: when I was running @chrp’s build it would (maybe only after some time?) ping me up to 60 seconds late. Presumably it was checking once a minute if a ping had happened. I’m hoping that was intentional and we can just undo that bit and otherwise merge in all of @chrp’s changes!


#7

Hello @dreev thanks for the feedback, I’ll investigate this. I don’t remember making any change that could have caused it.

I have a few questions to pinpoint the cause:

  • Does it happen when the screen is on too? To check that, please set a screen off delay on your device of 10 minutes and a ping gap of 2 minutes.
  • What version of Android are you running and what model/brand is your phone?

A possible cause would be the Doze feature of Android. It is a special mode that occurs when your screen is off and the device stays still for a time. In that mode, applications are only allowed to wake the device every few minutes.

In any case I don’t know of a way to guarantee that the notification will occur at the exact same time as a ping.


#8

I haven’t noticed this delay problem on mine.

Can Doze be turned off?


#9

Thanks so much for debugging! I was hoping you’d dialed down some polling frequency (a reasonable thing to do, just that I have other devices pinging in our house and it would really throw me off to hear the ping elsewhere and then have to wait up to a minute to answer it!) and it would be an easy change. Anyway, answers:

Affirmative.

Pixel 2, Android version: 9

This delay was happening when I was on version 8 as well, I’m pretty sure.

PS: @zedmango, for me this only happens on the build from @chrp, not the version on Google Play.
PPS: So I think we’ve ruled out the Doze feature.
PPPS: But maybe the Android OS is just being stingier with apps not from Google Play?


#10

@dreev I built from the most recent code in the github. That includes chrp’s changes, which were merged in 6 months ago, and the most recent changes which you made 4 months ago.


#11

@chrp @dreev
I just had this happen - ping should have hit at 12:00:06 pm today but I did not get notified until 12:01:00.


#12

@chrp @dreev

There’s a setting to not optimize power use per app - I’m gonna try this and see if it helps


#13

@dreev @chrp

Did not help - ping should have hit at 5:19:55 and I got it at about 5:20:50.

Are you sure this was not a problem before chrp’s changes were merged? It might have something to do with the Android version and not chrp’s changes.


#14

Hi folks!

There are at least two types of Android power savings–Doze, and App Standby. You can learn an OK overview here: https://developer.android.com/training/monitoring-device-state/doze-standby. You can use adb commands to force your app to be in them for testing.

It is very possible it is simply impossible for Tagtime to work well with modern Android. For instance, in Doze mode, you can set an alarm to override Doze, using setExactAndAllowWhileIdle, however:

To reduce abuse, there are restrictions on how frequently these alarms will go off for a particular application. Under normal system operation, it will not dispatch these alarms more than about every minute (at which point every such pending alarm is dispatched); when in low-power idle modes this duration may be significantly longer, such as 15 minutes.

In terms of workarounds, you can use Firebase Cloud Messaging to wake the app, but that requires network. You can also add a foreground service, which has to have a persistent notification. (Users can hide it using the system settings, but the app can’t hide it.)

I am trying to be positive about this, but please note some of this will change every year, and which portions of this apply in any instance will depend both upon the target Android version of the app, and the actual version of Android running on the device. There are at least two errors in that App Standby-Doze page from Android. I told them about them a few months ago, and they’re still there.


#15

@chrp

@adamwolf Thanks for that link. What are the two errors?

I tried whitelisting TagTime as shown in the illustration above, but according to that link:

the system provides a configurable whitelist of apps that are partially exempt from Doze and App Standby optimizations. An app that is whitelisted can use the network and hold partial wake locks during Doze and App Standby. However, other restrictions still apply to the whitelisted app, just as they do to other apps. For example, the whitelisted app’s jobs and syncs are deferred (on API level 23 and below), and its regular AlarmManager alarms do not fire.

So it looks like even whitelisting TagTime does not fix the “about every minute” problem.

Looking at the code, the alarm is set using setExactAndAllowWhileIdle:

https://github.com/tagtime/TagTime/blob/master/src/and/tagTime/src/main/java/bsoule/tagtime/PingService.java line 301

But in Doze, “alarms set with setAlarmClock() continue to fire normally — the system exits Doze shortly before those alarms fire.”

So can we just replace setExactAndAllowWhileIdle with setAlarmClock?

Adam, you wrote:

In terms of workarounds, you can use Firebase Cloud Messaging to wake the app, but that requires network. You can also add a foreground service, which has to have a persistent notification. (Users can hide it using the system settings, but the app can’t hide it.)

From reading your link, it looks like there are two separate issues: Doze and App Standby. It looks like the foreground service workaround addresses just App Standby, not Doze.

Another exception for App Standby is if:

The app is an active device admin app (for example, a device policy controller). Although they generally run in the background, device admin apps never enter App Standby because they must remain available to receive policy from a server at any time.

So it might be possible to just declare TagTime a “active device admin app” somehow. Failing that we can just add a persistent notification.

@dreev says he also sees this problem happening with the screen on, though. I have only seen it when the screen is off, using the most recent github.


#16

Definitely not sure and it’s looking less likely since @chrp doesn’t seem to have done anything that would explain it. But it does seem that I had this problem with the build I got from @chrp and don’t have it with the version from Google Play. If that’s in doubt I can try going back to a new build and see if it’s unambiguously true that the Google Play version gets the ping timing right and other builds don’t.

I did try all the things with disabling battery optimization etc etc. Nothing had any affect on the delayed pings. And I don’t need to fuss with any of that for the ping timing to be correct with the Google Play version.

Btw, note that it’s a random delay of 0 to 60 seconds. Sometimes you’ll be lucky and seem to see little or no delay.

PS: Huge thanks to @adamwolf for explaining the general situation with Android and notifications. For something like TagTime it actually seems kind of reasonable to have a persistent notification. Like it’s affirming that it’s always running and ready to ping at any moment. Not a crazy design choice. It will be more sad if Beedroid requires a persistent notification because it should only need to notify you at certain times that are mostly known ahead of time (assuming very occasional checkins with the server) and it doesn’t need to-the-second precision on those or anything.


#17

Is it possible that chrp’s build changes the target API level?


#18

It does.


#19

So by changing the target API level, that changes the baseline behavior for what Android is doing with the app. I bet if the only changes you made were to change the target API level to the version that is currently on Play, you’d get the same issue.

Next wrinkle: Google Play no longer accepts new apps or updates to existing apps that do not target API 26 or higher.


#20

@zedmango

So can we just replace setExactAndAllowWhileIdle with setAlarmClock?

Yes it would be possible BUT setAlarmClock causes Android to display a clock in the status bar and to display the time of the next alarm. So the user would know the time of the next ping.

@adamwolf

You can also add a foreground service, which has to have a persistent notification. (Users can hide it using the system settings, but the app can’t hide it.)

I think this would be the best compromise, but I would prefer to make it an optional behavior.

How would you see this in code with the foreground service and the persistent notification?