Merge pull request #41 from eternal-flame-AD/upstream-patch-network

listen for network changes
This commit is contained in:
Jannis Mattheis
2019-01-06 12:38:45 +01:00
committed by GitHub
5 changed files with 105 additions and 16 deletions

View File

@@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application <application
android:allowBackup="false" android:allowBackup="false"

View File

@@ -0,0 +1,30 @@
package com.github.gotify.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import com.github.gotify.log.Log;
public class ReconnectListener extends BroadcastReceiver {
private Runnable reconnected;
ReconnectListener(Runnable reconnected) {
this.reconnected = reconnected;
}
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager cm =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo network = cm.getActiveNetworkInfo();
if (network != null && network.isConnected()) {
Log.i("Network reconnected");
reconnected.run();
}
}
}

View File

@@ -1,5 +1,7 @@
package com.github.gotify.service; package com.github.gotify.service;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler; import android.os.Handler;
import com.github.gotify.SSLSettings; import com.github.gotify.SSLSettings;
import com.github.gotify.Utils; import com.github.gotify.Utils;
@@ -16,9 +18,11 @@ import okhttp3.WebSocket;
import okhttp3.WebSocketListener; import okhttp3.WebSocketListener;
public class WebSocketConnection { public class WebSocketConnection {
private final ConnectivityManager connectivityManager;
private OkHttpClient client; private OkHttpClient client;
private final Handler handler = new Handler(); private final Handler reconnectHandler = new Handler();
private Runnable reconnectCallback = this::start;
private int errorCount = 0; private int errorCount = 0;
private final String baseUrl; private final String baseUrl;
@@ -28,11 +32,17 @@ public class WebSocketConnection {
private Runnable onClose; private Runnable onClose;
private Runnable onOpen; private Runnable onOpen;
private BadRequestRunnable onBadRequest; private BadRequestRunnable onBadRequest;
private OnFailureCallback onFailure; private OnNetworkFailureRunnable onNetworkFailure;
private Runnable onReconnected; private Runnable onReconnected;
private boolean isClosed; private boolean isClosed;
private Runnable onDisconnect;
WebSocketConnection(String baseUrl, SSLSettings settings, String token) { WebSocketConnection(
String baseUrl,
SSLSettings settings,
String token,
ConnectivityManager connectivityManager) {
this.connectivityManager = connectivityManager;
OkHttpClient.Builder builder = OkHttpClient.Builder builder =
new OkHttpClient.Builder() new OkHttpClient.Builder()
.readTimeout(0, TimeUnit.MILLISECONDS) .readTimeout(0, TimeUnit.MILLISECONDS)
@@ -66,8 +76,13 @@ public class WebSocketConnection {
return this; return this;
} }
synchronized WebSocketConnection onFailure(OnFailureCallback onFailure) { synchronized WebSocketConnection onDisconnect(Runnable onDisconnect) {
this.onFailure = onFailure; this.onDisconnect = onDisconnect;
return this;
}
synchronized WebSocketConnection onNetworkFailure(OnNetworkFailureRunnable onNetworkFailure) {
this.onNetworkFailure = onNetworkFailure;
return this; return this;
} }
@@ -104,7 +119,18 @@ public class WebSocketConnection {
} }
} }
public synchronized void scheduleReconnect(long millis) {
reconnectHandler.removeCallbacks(reconnectCallback);
Log.i(
"WebSocket: scheduling a restart in "
+ TimeUnit.SECONDS.convert(millis, TimeUnit.MILLISECONDS)
+ " second(s)");
reconnectHandler.postDelayed(reconnectCallback, millis);
}
private class Listener extends WebSocketListener { private class Listener extends WebSocketListener {
@Override @Override
public void onOpen(WebSocket webSocket, Response response) { public void onOpen(WebSocket webSocket, Response response) {
Log.i("WebSocket: opened"); Log.i("WebSocket: opened");
@@ -153,14 +179,19 @@ public class WebSocketConnection {
return; return;
} }
int minutes = Math.min(errorCount * 2 + 1, 20);
Log.i("WebSocket: trying to restart in " + minutes + " minute(s)");
errorCount++; errorCount++;
handler.postDelayed(
WebSocketConnection.this::start, TimeUnit.MINUTES.toMillis(minutes)); NetworkInfo network = connectivityManager.getActiveNetworkInfo();
onFailure.execute(minutes); if (network == null || !network.isConnected()) {
Log.i("WebSocket: Network not connected");
onDisconnect.run();
return;
}
int minutes = Math.min(errorCount * 2 - 1, 20);
onNetworkFailure.execute(minutes);
scheduleReconnect(TimeUnit.MINUTES.toMillis(minutes));
} }
super.onFailure(webSocket, t, response); super.onFailure(webSocket, t, response);
@@ -171,7 +202,7 @@ public class WebSocketConnection {
void execute(String message); void execute(String message);
} }
interface OnFailureCallback { interface OnNetworkFailureRunnable {
void execute(int minutesToTryAgain); void execute(long millis);
} }
} }

View File

@@ -6,7 +6,9 @@ import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color; import android.graphics.Color;
import android.net.ConnectivityManager;
import android.os.Build; import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -25,6 +27,7 @@ import com.github.gotify.log.Log;
import com.github.gotify.log.UncaughtExceptionHandler; import com.github.gotify.log.UncaughtExceptionHandler;
import com.github.gotify.messages.MessagesActivity; import com.github.gotify.messages.MessagesActivity;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public class WebSocketService extends Service { public class WebSocketService extends Service {
@@ -84,15 +87,38 @@ public class WebSocketService extends Service {
missingMessageUtil.lastReceivedMessage(lastReceivedMessage::set); missingMessageUtil.lastReceivedMessage(lastReceivedMessage::set);
} }
ConnectivityManager cm =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
connection = connection =
new WebSocketConnection(settings.url(), settings.sslSettings(), settings.token()) new WebSocketConnection(
settings.url(), settings.sslSettings(), settings.token(), cm)
.onOpen(this::onOpen) .onOpen(this::onOpen)
.onClose(() -> foreground(getString(R.string.websocket_closed))) .onClose(() -> foreground(getString(R.string.websocket_closed)))
.onBadRequest(this::onBadRequest) .onBadRequest(this::onBadRequest)
.onFailure((min) -> foreground(getString(R.string.websocket_failed, min))) .onNetworkFailure(
(min) -> foreground(getString(R.string.websocket_failed, min)))
.onDisconnect(this::onDisconnect)
.onMessage(this::onMessage) .onMessage(this::onMessage)
.onReconnected(this::notifyMissedNotifications) .onReconnected(this::notifyMissedNotifications)
.start(); .start();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
ReconnectListener receiver = new ReconnectListener(this::doReconnect);
registerReceiver(receiver, intentFilter);
}
private void onDisconnect() {
foreground(getString(R.string.websocket_no_network));
}
private void doReconnect() {
if (connection == null) {
return;
}
connection.scheduleReconnect(TimeUnit.SECONDS.toMillis(5));
} }
private void onBadRequest(String message) { private void onBadRequest(String message) {

View File

@@ -57,4 +57,5 @@
<string name="warning">Warning</string> <string name="warning">Warning</string>
<string name="http_warning">Using http is insecure and it\'s recommend to use https instead. Use your favorite search engine to get more information about this topic.</string> <string name="http_warning">Using http is insecure and it\'s recommend to use https instead. Use your favorite search engine to get more information about this topic.</string>
<string name="i_understand">I Understand</string> <string name="i_understand">I Understand</string>
<string name="websocket_no_network">Waiting for network</string>
</resources> </resources>