mirror of https://github.com/nextcloud/android
157 lines
5.9 KiB
Java
157 lines
5.9 KiB
Java
/*
|
|
* Nextcloud Android client application
|
|
*
|
|
* @author Chris Narkiewicz
|
|
* Copyright (C) 2021 Chris Narkiewicz <hello@ezaquarii.com>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
package com.nextcloud.client.network;
|
|
|
|
import android.net.ConnectivityManager;
|
|
import android.net.Network;
|
|
import android.net.NetworkCapabilities;
|
|
import android.net.NetworkInfo;
|
|
|
|
import com.nextcloud.client.account.Server;
|
|
import com.nextcloud.client.account.UserAccountManager;
|
|
import com.nextcloud.common.PlainClient;
|
|
import com.nextcloud.operations.GetMethod;
|
|
import com.owncloud.android.lib.common.utils.Log_OC;
|
|
|
|
import org.apache.commons.httpclient.HttpStatus;
|
|
|
|
import androidx.core.net.ConnectivityManagerCompat;
|
|
import kotlin.jvm.functions.Function1;
|
|
|
|
class ConnectivityServiceImpl implements ConnectivityService {
|
|
|
|
private static final String TAG = "ConnectivityServiceImpl";
|
|
private static final String CONNECTIVITY_CHECK_ROUTE = "/index.php/204";
|
|
|
|
private final ConnectivityManager platformConnectivityManager;
|
|
private final UserAccountManager accountManager;
|
|
private final ClientFactory clientFactory;
|
|
private final GetRequestBuilder requestBuilder;
|
|
private final WalledCheckCache walledCheckCache;
|
|
|
|
static class GetRequestBuilder implements Function1<String, GetMethod> {
|
|
@Override
|
|
public GetMethod invoke(String url) {
|
|
return new GetMethod(url, false);
|
|
}
|
|
}
|
|
|
|
ConnectivityServiceImpl(ConnectivityManager platformConnectivityManager,
|
|
UserAccountManager accountManager,
|
|
ClientFactory clientFactory,
|
|
GetRequestBuilder requestBuilder,
|
|
final WalledCheckCache walledCheckCache) {
|
|
this.platformConnectivityManager = platformConnectivityManager;
|
|
this.accountManager = accountManager;
|
|
this.clientFactory = clientFactory;
|
|
this.requestBuilder = requestBuilder;
|
|
this.walledCheckCache = walledCheckCache;
|
|
}
|
|
|
|
@Override
|
|
public boolean isConnected() {
|
|
Network nw = platformConnectivityManager.getActiveNetwork();
|
|
NetworkCapabilities actNw = platformConnectivityManager.getNetworkCapabilities(nw);
|
|
|
|
if (actNw == null) {
|
|
return false;
|
|
}
|
|
|
|
return actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
|
|
actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
|
|
actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
|
|
actNw.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH);
|
|
}
|
|
|
|
@Override
|
|
public boolean isInternetWalled() {
|
|
final Boolean cachedValue = walledCheckCache.getValue();
|
|
if (cachedValue != null) {
|
|
return cachedValue;
|
|
} else {
|
|
boolean result;
|
|
Connectivity c = getConnectivity();
|
|
if (c.isConnected() && c.isWifi() && !c.isMetered()) {
|
|
|
|
Server server = accountManager.getUser().getServer();
|
|
String baseServerAddress = server.getUri().toString();
|
|
if (baseServerAddress.isEmpty()) {
|
|
result = true;
|
|
} else {
|
|
|
|
GetMethod get = requestBuilder.invoke(baseServerAddress + CONNECTIVITY_CHECK_ROUTE);
|
|
PlainClient client = clientFactory.createPlainClient();
|
|
|
|
int status = get.execute(client);
|
|
|
|
// Content-Length is not available when using chunked transfer encoding, so check for -1 as well
|
|
result = !(status == HttpStatus.SC_NO_CONTENT && get.getResponseContentLength() <= 0);
|
|
get.releaseConnection();
|
|
if (result) {
|
|
Log_OC.w(TAG, "isInternetWalled(): Failed to GET " + CONNECTIVITY_CHECK_ROUTE + "," +
|
|
" assuming connectivity is impaired");
|
|
}
|
|
}
|
|
} else {
|
|
result = !c.isConnected();
|
|
}
|
|
|
|
walledCheckCache.setValue(result);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Connectivity getConnectivity() {
|
|
NetworkInfo networkInfo;
|
|
try {
|
|
networkInfo = platformConnectivityManager.getActiveNetworkInfo();
|
|
} catch (Throwable t) {
|
|
networkInfo = null; // no network available or no information (permission denied?)
|
|
}
|
|
|
|
if (networkInfo != null) {
|
|
boolean isConnected = networkInfo.isConnectedOrConnecting();
|
|
// more detailed check
|
|
boolean isMetered;
|
|
isMetered = isNetworkMetered();
|
|
boolean isWifi = networkInfo.getType() == ConnectivityManager.TYPE_WIFI || hasNonCellularConnectivity();
|
|
return new Connectivity(isConnected, isMetered, isWifi, null);
|
|
} else {
|
|
return Connectivity.DISCONNECTED;
|
|
}
|
|
}
|
|
|
|
private boolean isNetworkMetered() {
|
|
final Network network = platformConnectivityManager.getActiveNetwork();
|
|
try {
|
|
NetworkCapabilities networkCapabilities = platformConnectivityManager.getNetworkCapabilities(network);
|
|
if (networkCapabilities != null) {
|
|
return !networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
|
|
} else {
|
|
return ConnectivityManagerCompat.isActiveNetworkMetered(platformConnectivityManager);
|
|
}
|
|
} catch (RuntimeException e) {
|
|
Log_OC.e(TAG, "Exception when checking network capabilities", e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private boolean hasNonCellularConnectivity() {
|
|
for (NetworkInfo networkInfo : platformConnectivityManager.getAllNetworkInfo()) {
|
|
if (networkInfo.isConnectedOrConnecting() && (networkInfo.getType() == ConnectivityManager.TYPE_WIFI ||
|
|
networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|