diff --git a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/NetworkManager.java b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/NetworkManager.java index abe629322..e283cd56d 100644 --- a/src/frontends/android/app/src/main/java/org/strongswan/android/logic/NetworkManager.java +++ b/src/frontends/android/app/src/main/java/org/strongswan/android/logic/NetworkManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Tobias Brunner + * Copyright (C) 2012-2019 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +20,10 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; +import android.net.Network; import android.net.NetworkInfo; +import android.net.NetworkRequest; +import android.os.Build; import java.util.LinkedList; @@ -28,12 +31,45 @@ public class NetworkManager extends BroadcastReceiver implements Runnable { private final Context mContext; private volatile boolean mRegistered; + private ConnectivityManager.NetworkCallback mCallback; private Thread mEventNotifier; + private int mConnectedNetworks = 0; private LinkedList mEvents = new LinkedList<>(); public NetworkManager(Context context) { mContext = context; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + { + mCallback = new ConnectivityManager.NetworkCallback() + { + @Override + public void onAvailable(Network network) + { + synchronized (NetworkManager.this) + { + /* we expect this to be called if connected to at least one network during + * callback registration */ + mConnectedNetworks += 1; + mEvents.addLast(true); + NetworkManager.this.notifyAll(); + } + } + + @Override + public void onLost(Network network) + { + synchronized (NetworkManager.this) + { + /* in particular mobile connections are disconnected overlapping with WiFi */ + mConnectedNetworks -= 1; + mEvents.addLast(mConnectedNetworks > 0); + NetworkManager.this.notifyAll(); + } + } + }; + } } public void Register() @@ -42,12 +78,38 @@ public class NetworkManager extends BroadcastReceiver implements Runnable mRegistered = true; mEventNotifier = new Thread(this); mEventNotifier.start(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + { + ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + /* while we only get events for the VPN network via registerDefaultNetworkCallback, + * the default capabilities in the builder include NetworkCapabilities.NET_CAPABILITY_NOT_VPN */ + NetworkRequest.Builder builder = new NetworkRequest.Builder(); + cm.registerNetworkCallback(builder.build(), mCallback); + } + else + { + registerLegacyReceiver(); + } + } + + @SuppressWarnings("deprecation") + private void registerLegacyReceiver() + { + /* deprecated since API level 28 */ mContext.registerReceiver(this, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); } public void Unregister() { - mContext.unregisterReceiver(this); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + { + ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + cm.unregisterNetworkCallback(mCallback); + } + else + { + mContext.unregisterReceiver(this); + } mRegistered = false; synchronized (this) {