你好,我有一个简单的应用程序,我所做的是当用户没有连接到互联网,而启动应用程序,它会显示一个文本视图"没有互联网"但问题是,当我启动互联网或连接到任何网络时它不会显示原始视图我要做的是关闭应用程序并再次打开以显示主视图
当连接打开/关闭时,我如何在这两个视图之间实时切换
onCreate
// Internet on/off
if (isOnline()) {
noInternet.setVisibility(View.INVISIBLE); // Online
mainRelativeLayout.setVisibility(View.VISIBLE);
} else {
noInternet.setVisibility(View.VISIBLE); // Disconnected
mainRelativeLayout.setVisibility(View.INVISIBLE);
}
这是我目前使用的获取连接信息
// Internet on/off
public boolean isOnline() {
boolean connected = false;
try {
ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
connected = networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected();
return connected;
} catch (Exception e) {
e.printStackTrace();
}
return connected;
}
要实时观察连接变化,可以使用LiveData。在此之前,我们使用BroadcastReceiver,但正如您所看到的Declaring a broadcastreceiver for android.net.conn.CONNECTIVITY_CHANGE is deprecated for apps targeting N and higher.
我将发布完整的代码并解释它的每一部分。
public class ConnectionLiveData extends LiveData<Boolean> {
private ConnectivityManager.NetworkCallback networkCallback;
private final ConnectivityManager cm;
private final HashSet<Network> validNetworks = new HashSet<>();
private final ExecutorService executor = Executors.newSingleThreadExecutor();
public static final int NETWORK_STATUS_POST_DELAY = 1000;
public ConnectionLiveData(Context context) {
cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
private void checkValidNetworks() {
new Handler(Looper.getMainLooper()).postDelayed(() ->
postValue(validNetworks.size() > 0),
NETWORK_STATUS_POST_DELAY);
}
@Override
protected void onActive() {
networkCallback = createNetworkCallback();
NetworkRequest networkRequest = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
cm.registerNetworkCallback(networkRequest, networkCallback);
}
@Override
protected void onInactive() {
cm.unregisterNetworkCallback(networkCallback);
}
private ConnectivityManager.NetworkCallback createNetworkCallback() {
return new ConnectivityManager.NetworkCallback() {
/*
Called when a network is detected. If that network has internet, save it in the Set.
Source: https://developer.android.com/reference/android/net/ConnectivityManager.NetworkCallback#onAvailable(android.net.Network)
*/
@Override
public void onAvailable(@NonNull Network network) {
NetworkCapabilities capabilities = cm.getNetworkCapabilities(network);
boolean hasInternetCapability = capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
if (hasInternetCapability) {
// check if this network actually has internet
executor.execute(() -> {
boolean hasInternet = DoesNetworkHaveInternet.execute(network.getSocketFactory());
if (hasInternet) {
validNetworks.add(network);
checkValidNetworks();
}
});
}
}
/*
If the callback was registered with registerNetworkCallback() it will be called for each network which no longer satisfies the criteria of the callback.
Source: https://developer.android.com/reference/android/net/ConnectivityManager.NetworkCallback#onLost(android.net.Network)
*/
@Override
public void onLost(@NonNull Network network) {
validNetworks.remove(network);
checkValidNetworks();
}
};
}
}
我们在这里扩展了LiveData
,实现了onActive()
和onInactive()
两个函数。正如您所知,LiveData
是生命周期感知的,当存在一个观察者时,将调用onActive
。我用它们来注册/注销ConnectivityManager
。当我们注册ConnectivityManager
时,我们传递一个networkCallback
作为参数。它有几个方法,但是正如您在createNetworkCallback()
函数中看到的,我们只覆盖onAvailable()
和onLost()
函数。如果你打开/关闭你的网络,onAvailable()
和onLost()
将被调用。
可能存在连接打开但与服务器没有连接的情况。在本例中,我找到了一个简单的类,我们可以使用它来ping和验证我们的连接。使用ExecutorService
,我通过ping验证internet连接。
boolean hasInternet = DoesNetworkHaveInternet.execute(network.getSocketFactory());
DoesNetworkHaveInternet
代码:
public class DoesNetworkHaveInternet {
private static final String HOST_NAME = "8.8.8.8";
private static final int PORT = 53;
private static final int CONNECT_TIMEOUT = 1500;
@WorkerThread
static Boolean execute(SocketFactory socketFactory) {
try {
Socket socket = socketFactory.createSocket();
socket.connect(new InetSocketAddress(HOST_NAME, PORT), CONNECT_TIMEOUT);
socket.close();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
}
它正在ping,并验证我们有一个稳定的连接。最后,在验证我们有连接之后,我们调用checkValidNetworks()
函数。有一个延迟,因为在某些情况下,你的连接可能会关闭和打开一会儿,为此我发现没有必要显示网络错误。checkValidNetworks()
检查validNetworks
是否为空。这是一个列表,因为有一些类型的连接,如wifi和移动网络。如果至少有一个稳定连接,validNetworks
将不会为空。就是这样。您可以在fragment或activity中观察它,如下所示:
ConnectionLiveDataJava connectionLiveData = new ConnectionLiveDataJava(this);
connectionLiveData.observe(this, isConnected -> {
});
我插入你的代码也把零食栏在我现有的项目。但有两种情况发生
- 当每个活动开始时,它的零食栏显示。如何只停止第一个活动显示其他人没有。
- 如果在第一次运行时没有连接互联网。它显示没有零食。请看这个