-
Notifications
You must be signed in to change notification settings - Fork 613
Use manual foreground detection to trigger network reconnect #2763
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
46cbc04
to
cbdd29f
Compare
cbdd29f
to
f3a5738
Compare
Coverage ReportAffected SDKs
Test Logs
NotesHTML coverage reports can be produced locally with Head commit (e0e64817) is created by Prow via merging commits: 563781c d9051b6. |
Binary Size ReportAffected SDKs
Test Logs
NotesHead commit (e0e64817) is created by Prow via merging commits: 563781c d9051b6. |
Looks like this broke a test. |
// Only raise the foreground notification if the same activity when to the | ||
// background before. This prevents notifications when an app switches between | ||
// activities. | ||
if (activity == lastActivity) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@samtstern Does this code make sense? I would like to detect when an app goes into the background and then back into the foreground. I assume that in this case, we will get a notification with the same activity, whereas in the normal app lifecycle we will receive this notification with a different activity.
Do you also happen to know if the memory address here will always be the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a feeling activity == lastActivity
is going to be too simple, as Android destroys activities all the time. That's why you need to do all the savedInstanceState
stuff to handle device rotation.
But I don't know the more robust way to handle Activity
comparison.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moreover, holding a strong reference to an Activity
leaks the Activity
instance, causing a memory leak. As Sam mentions, the Activity
instances would compare unequal even if it was the same activity but some "configuration change" caused the Activity
to be destroyed and re-created, such as a screen rotation.
What if you instead compared the activity's Intent
for equality? Holding a strong reference to an Intent
is not a memory leak and it more-or-less describes the Activity
. It's not perfect, because, in theory, you can start a new Activity
with the exact same Intent
overtop of itself. But I think that situation is fairly rare.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the implementation to also hook into the component callbacks, which offer a notification when an app's UI becomes hidden. This is also used here: cs/piper///depot/google3/java/com/google/android/gmscore/integ/client/common/src/com/google/android/gms/common/api/internal/BackgroundDetector.java;l=140
The code is now very similar to BackgroundDetector, but it also fires if the state transition is not 100% certain. In my testing, it works to detect the transitions, whereas BackgroundDetector sometimes misses a transition. It is likely better to fire more often then to miss a transition.
/test smoke-tests |
firebase-firestore/CHANGELOG.md
Outdated
@@ -1,4 +1,8 @@ | |||
# Unreleased | |||
# Unreelased |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: "Unreelased"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
firebase-firestore/CHANGELOG.md
Outdated
# Unreleased | ||
# Unreelased | ||
- [changed] Increases the aggressiveness of network retires when an app's | ||
visibility status changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is "visibility" the right term here? Would it make more sense to just say "foreground status"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That might be better. Updated.
// Only raise the foreground notification if the same activity when to the | ||
// background before. This prevents notifications when an app switches between | ||
// activities. | ||
if (activity == lastActivity) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moreover, holding a strong reference to an Activity
leaks the Activity
instance, causing a memory leak. As Sam mentions, the Activity
instances would compare unequal even if it was the same activity but some "configuration change" caused the Activity
to be destroyed and re-created, such as a screen rotation.
What if you instead compared the activity's Intent
for equality? Holding a strong reference to an Intent
is not a memory leak and it more-or-less describes the Activity
. It's not perfect, because, in theory, you can start a new Activity
with the exact same Intent
overtop of itself. But I think that situation is fairly rare.
73d64eb
to
9b0cebd
Compare
} | ||
} | ||
|
||
private void configureBackgroundStateListener() { | ||
BackgroundDetector.getInstance().addListener(this); | ||
Application applicationContext = (Application) context.getApplicationContext(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: applicationContext
can be renamed to application
since it is being casted to an instance of Application
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
@Override | ||
public void onActivityResumed(@NonNull Activity activity) { | ||
if (inBackground.compareAndSet(true, false)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider putting the body of onActivityResumed()
into onActivityCreated()
as well, so that the "offline" state is updated as early as possible (this is what BackgroundDetector
does). Even copy it into onActivityStarted()
too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea. It might not make a huge difference in practice since bringing up the network is a pretty heavy operation on its own, but it certainly should not hut (at least I would hope so).
This is a follow up to #2693, which used Android's built-in BackgroundDetector to fast-forward network reconnects when an app entered the foreground. Unfortunately, the BackgroundDetector is pretty conservative and only fires if it knows for certain that the app was in the background and now is in the foreground. This leads to some suppressed notifications. This PR just hooks directly into the notification API and always raises the foreground notification.
Logs:
Fixes #2637