Skip to content

Skip backoff when App enters Foreground #2693

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

Merged
merged 1 commit into from
May 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions firebase-firestore/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Unreleased
- [changed] The SDK now tries to immediately establish a connection to the
backend when the app enters the foreground.

# 22.1.1
- [fixed] Fixed an issue that dropped the limit for queries loaded from
Bundles that were generated by the NodeJS SDK.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import android.net.Network;
import android.os.Build;
import androidx.annotation.Nullable;
import com.google.android.gms.common.api.internal.BackgroundDetector;
import com.google.firebase.firestore.util.Consumer;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -35,7 +36,8 @@
* <p>Implementation note: Most of the code here was shamelessly stolen from
* https://github.com/grpc/grpc-java/blob/master/android/src/main/java/io/grpc/android/AndroidChannelBuilder.java
*/
public final class AndroidConnectivityMonitor implements ConnectivityMonitor {
public final class AndroidConnectivityMonitor
implements ConnectivityMonitor, BackgroundDetector.BackgroundStateChangeListener {

private final Context context;
@Nullable private final ConnectivityManager connectivityManager;
Expand All @@ -50,6 +52,7 @@ public AndroidConnectivityMonitor(Context context) {

connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
configureBackgroundStateListener();
configureNetworkMonitoring();
}

Expand Down Expand Up @@ -96,53 +99,60 @@ public void run() {
}
}

private void configureBackgroundStateListener() {
BackgroundDetector.getInstance().addListener(this);
}

@Override
public void onBackgroundStateChanged(boolean background) {
if (!background && isConnected()) {
raiseCallbacks(/* connected= */ true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is invoking the callbacks enough to reset the backoff? (I presume it is, just checking)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, they already call inhibitBackoff.

}
}

/** Respond to changes in the default network. Only used on API levels 24+. */
@TargetApi(Build.VERSION_CODES.N)
private class DefaultNetworkCallback extends ConnectivityManager.NetworkCallback {
@Override
public void onAvailable(Network network) {
synchronized (callbacks) {
for (Consumer<NetworkStatus> callback : callbacks) {
callback.accept(NetworkStatus.REACHABLE);
}
}
raiseCallbacks(/* connected= */ true);
}

@Override
public void onLost(Network network) {
synchronized (callbacks) {
for (Consumer<NetworkStatus> callback : callbacks) {
callback.accept(NetworkStatus.UNREACHABLE);
}
}
raiseCallbacks(/* connected= */ false);
}
}

/** Respond to network changes. Only used on API levels < 24. */
private class NetworkReceiver extends BroadcastReceiver {
private boolean isConnected = false;
private boolean wasConnected = false;

@Override
@SuppressWarnings("deprecation")
public void onReceive(Context context, Intent intent) {
ConnectivityManager conn =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
android.net.NetworkInfo networkInfo = conn.getActiveNetworkInfo();
boolean wasConnected = isConnected;
isConnected = networkInfo != null && networkInfo.isConnected();
if (isConnected && !wasConnected) {
synchronized (callbacks) {
for (Consumer<NetworkStatus> callback : callbacks) {
callback.accept(NetworkStatus.REACHABLE);
}
}
boolean isConnected = isConnected();
if (isConnected() && !wasConnected) {
raiseCallbacks(/* connected= */ true);
} else if (!isConnected && wasConnected) {
synchronized (callbacks) {
for (Consumer<NetworkStatus> callback : callbacks) {
callback.accept(NetworkStatus.UNREACHABLE);
}
}
raiseCallbacks(/* connected= */ false);
}
wasConnected = isConnected;
}
}

private void raiseCallbacks(boolean connected) {
synchronized (callbacks) {
for (Consumer<NetworkStatus> callback : callbacks) {
callback.accept(connected ? NetworkStatus.REACHABLE : NetworkStatus.UNREACHABLE);
}
}
}

private boolean isConnected() {
ConnectivityManager conn =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
android.net.NetworkInfo networkInfo = conn.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
}