2424
2525import org .apache .commons .httpclient .HttpStatus ;
2626
27+ import java .util .concurrent .ExecutorService ;
28+ import java .util .concurrent .Executors ;
29+
2730import androidx .annotation .NonNull ;
28- import androidx .core .net .ConnectivityManagerCompat ;
2931import kotlin .jvm .functions .Function1 ;
3032
3133class ConnectivityServiceImpl implements ConnectivityService {
@@ -38,6 +40,7 @@ class ConnectivityServiceImpl implements ConnectivityService {
3840 private final ClientFactory clientFactory ;
3941 private final GetRequestBuilder requestBuilder ;
4042 private final WalledCheckCache walledCheckCache ;
43+ private final ExecutorService executor = Executors .newSingleThreadExecutor ();
4144 private final Handler mainThreadHandler = new Handler (Looper .getMainLooper ());
4245
4346 static class GetRequestBuilder implements Function1 <String , GetMethod > {
@@ -61,22 +64,28 @@ public GetMethod invoke(String url) {
6164
6265 @ Override
6366 public void isNetworkAndServerAvailable (@ NonNull GenericCallback <Boolean > callback ) {
64- new Thread (() -> {
65- Network activeNetwork = platformConnectivityManager .getActiveNetwork ();
66- NetworkCapabilities networkCapabilities = platformConnectivityManager .getNetworkCapabilities (activeNetwork );
67- boolean hasInternet = networkCapabilities != null && networkCapabilities .hasCapability (NetworkCapabilities .NET_CAPABILITY_INTERNET );
68-
69- boolean result ;
70- if (hasInternet ) {
71- result = !isInternetWalled ();
72- } else {
73- result = false ;
74- }
75-
76- mainThreadHandler .post (() -> callback .onComplete (result ));
77- }).start ();
67+ executor .submit (() -> {
68+ boolean isAvailable = !isInternetWalled ();
69+ mainThreadHandler .post (() -> callback .onComplete (isAvailable ));
70+ });
7871 }
7972
73+ /**
74+ * Checks whether the device is currently connected to a network
75+ * that has verified Internet access.
76+ *
77+ * <p>This method performs multiple levels of validation:
78+ * <ul>
79+ * <li>Ensures there is an active network connection.</li>
80+ * <li>Retrieves and checks network capabilities.</li>
81+ * <li>Verifies that the active network provides and has validated Internet access.</li>
82+ * <li>Confirms that the network uses a supported transport type
83+ * (Wi-Fi, Cellular, Ethernet, VPN, etc.).</li>
84+ * </ul>
85+ *
86+ * @return {@code true} if the device is connected to the Internet via a valid transport type;
87+ * {@code false} otherwise.
88+ */
8089 @ Override
8190 public boolean isConnected () {
8291 Network nw = platformConnectivityManager .getActiveNetwork ();
@@ -89,18 +98,28 @@ public boolean isConnected() {
8998 return false ;
9099 }
91100
92- if (actNw .hasCapability (NetworkCapabilities .NET_CAPABILITY_INTERNET ) ||
93- actNw .hasTransport (NetworkCapabilities .TRANSPORT_WIFI ) ||
94- actNw .hasTransport (NetworkCapabilities .TRANSPORT_CELLULAR ) ||
95- actNw .hasTransport (NetworkCapabilities .TRANSPORT_ETHERNET ) ||
96- actNw .hasTransport (NetworkCapabilities .TRANSPORT_VPN ) ||
97- actNw .hasTransport (NetworkCapabilities .TRANSPORT_BLUETOOTH ) ||
98- actNw .hasTransport (NetworkCapabilities .TRANSPORT_WIFI_AWARE )) {
99- return true ;
101+ // Verify that the network both claims to provide Internet
102+ // and has been validated (i.e., Internet is actually reachable).
103+ if (actNw .hasCapability (NetworkCapabilities .NET_CAPABILITY_INTERNET ) && actNw .hasCapability (NetworkCapabilities .NET_CAPABILITY_VALIDATED )) {
104+
105+ // Check if the active network uses one of the recognized transport types.
106+ if (actNw .hasTransport (NetworkCapabilities .TRANSPORT_WIFI ) ||
107+ actNw .hasTransport (NetworkCapabilities .TRANSPORT_CELLULAR ) ||
108+ actNw .hasTransport (NetworkCapabilities .TRANSPORT_ETHERNET ) ||
109+ actNw .hasTransport (NetworkCapabilities .TRANSPORT_VPN ) ||
110+ actNw .hasTransport (NetworkCapabilities .TRANSPORT_BLUETOOTH ) ||
111+ actNw .hasTransport (NetworkCapabilities .TRANSPORT_WIFI_AWARE )) {
112+
113+ // Connected through a valid, verified network transport.
114+ return true ;
115+ }
116+
117+ // If still nothing matched check Android 12 (API 31, "S") and above via USB network transport.
118+ return Build .VERSION .SDK_INT >= Build .VERSION_CODES .S &&
119+ actNw .hasTransport (NetworkCapabilities .TRANSPORT_USB );
100120 }
101121
102- return Build .VERSION .SDK_INT >= Build .VERSION_CODES .S &&
103- actNw .hasTransport (NetworkCapabilities .TRANSPORT_USB );
122+ return false ;
104123 }
105124
106125 @ Override
@@ -110,31 +129,36 @@ public boolean isInternetWalled() {
110129 return cachedValue ;
111130 }
112131
113- Server server = accountManager .getUser ().getServer ();
114- String baseServerAddress = server .getUri ().toString ();
115-
116- boolean result = false ;
117- if (isConnected () && !baseServerAddress .isEmpty ()) {
118- try {
119- GetMethod get = requestBuilder .invoke (baseServerAddress + CONNECTIVITY_CHECK_ROUTE );
120- PlainClient client = clientFactory .createPlainClient ();
121-
122- int status = get .execute (client );
123-
124- // Content-Length is not available when using chunked transfer encoding, so check for -1 as well
125- result = !(status == HttpStatus .SC_NO_CONTENT && get .getResponseContentLength () <= 0 );
126- get .releaseConnection ();
127- if (result ) {
128- Log_OC .w (TAG , "isInternetWalled(): Failed to GET " + CONNECTIVITY_CHECK_ROUTE + "," +
129- " assuming connectivity is impaired" );
130- }
131- } catch (Exception e ) {
132- Log_OC .e (TAG , "Exception while checking internet walled state" + e );
133- }
132+ final Server server = accountManager .getUser ().getServer ();
133+ final String baseServerAddress = server .getUri ().toString ();
134+
135+ if (!isConnected () || baseServerAddress .isEmpty ()) {
136+ walledCheckCache .setValue (true );
137+ return true ;
134138 }
135139
136- walledCheckCache .setValue (result );
137- return result ;
140+ final GetMethod get = requestBuilder .invoke (baseServerAddress + CONNECTIVITY_CHECK_ROUTE );
141+ try {
142+ final PlainClient client = clientFactory .createPlainClient ();
143+ int status = get .execute (client );
144+
145+ boolean isWalled = !(status == HttpStatus .SC_NO_CONTENT && get .getResponseContentLength () <= 0 );
146+
147+ if (isWalled ) {
148+ Log_OC .w (TAG , "isInternetWalled(): Failed to GET " + CONNECTIVITY_CHECK_ROUTE +
149+ ", assuming connectivity is impaired" );
150+ }
151+
152+ // Cache and return result
153+ walledCheckCache .setValue (isWalled );
154+ return isWalled ;
155+ } catch (Exception e ) {
156+ Log_OC .e (TAG , "Exception while checking internet walled state" , e );
157+ walledCheckCache .setValue (true );
158+ return true ;
159+ } finally {
160+ get .releaseConnection ();
161+ }
138162 }
139163
140164 @ Override
@@ -146,27 +170,12 @@ public Connectivity getConnectivity() {
146170
147171 NetworkCapabilities nc = platformConnectivityManager .getNetworkCapabilities (nw );
148172 boolean isConnected = isConnected ();
149- boolean isMetered = isNetworkMetered ( );
150- boolean isWifi = nc != null &&
173+ boolean isMetered = ( nc != null ) && ! nc . hasCapability ( NetworkCapabilities . NET_CAPABILITY_NOT_METERED );
174+ boolean isWifi = ( nc != null ) &&
151175 (nc .hasTransport (NetworkCapabilities .TRANSPORT_WIFI ) ||
152176 nc .hasTransport (NetworkCapabilities .TRANSPORT_ETHERNET ) ||
153177 nc .hasTransport (NetworkCapabilities .TRANSPORT_WIFI_AWARE ));
154178
155179 return new Connectivity (isConnected , isMetered , isWifi , null );
156180 }
157-
158- private boolean isNetworkMetered () {
159- final Network network = platformConnectivityManager .getActiveNetwork ();
160- try {
161- NetworkCapabilities networkCapabilities = platformConnectivityManager .getNetworkCapabilities (network );
162- if (networkCapabilities != null ) {
163- return !networkCapabilities .hasCapability (NetworkCapabilities .NET_CAPABILITY_NOT_RESTRICTED );
164- } else {
165- return ConnectivityManagerCompat .isActiveNetworkMetered (platformConnectivityManager );
166- }
167- } catch (RuntimeException e ) {
168- Log_OC .e (TAG , "Exception when checking network capabilities" , e );
169- return false ;
170- }
171- }
172181}
0 commit comments