如何在 Android 应用程序运行时后台持续检查网络连接状态?

12

我希望在我的 Android 应用程序运行期间持续检查互联网连接。也就是说,从应用程序开始到结束期间都要持续检查。我该如何做?应该采取什么方法?


您可以使用一个 service,从那里您可以检查网络是否可用。 - user3110424
请查看此链接:https://dev59.com/Zmkv5IYBdhLWcg3wxzyA#10350511 - user3110424
请参考我在这里的回答。希望能对您有所帮助。 - user957654
感谢Bibek、user3110424和Amrola的回答...我会告诉你哪个对我有效... - Manish
7个回答

6
我知道我回答这个问题有点晚了。 但是这里有一种在Activity/Fragment中持续监控网络连接的方法。
我们将使用Network Callback来监控我们在Activity/Fragment中的连接。
首先,在类中声明两个变量。
// to check if we are connected to Network
boolean isConnected = true;

// to check if we are monitoring Network
private boolean monitoringConnectivity = false;

接下来,我们将编写网络回调方法。
private ConnectivityManager.NetworkCallback connectivityCallback
            = new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            isConnected = true;
            LogUtility.LOGD(TAG, "INTERNET CONNECTED");
        }

        @Override
        public void onLost(Network network) {
            isConnected = false;
            LogUtility.LOGD(TAG, "INTERNET LOST");
        }
    };

现在,既然我们已经编写了回调函数,接下来我们将编写一个方法来监控我们的网络连接。在这个方法中,我们将注册我们的NetworkCallback。
// Method to check network connectivity in Main Activity
    private void checkConnectivity() {
        // here we are getting the connectivity service from connectivity manager
        final ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(
                Context.CONNECTIVITY_SERVICE);

        // Getting network Info
        // give Network Access Permission in Manifest
        final NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();

        // isConnected is a boolean variable
        // here we check if network is connected or is getting connected
        isConnected = activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting();

        if (!isConnected) {
            // SHOW ANY ACTION YOU WANT TO SHOW
            // WHEN WE ARE NOT CONNECTED TO INTERNET/NETWORK
            LogUtility.LOGD(TAG, " NO NETWORK!");
// if Network is not connected we will register a network callback to  monitor network
            connectivityManager.registerNetworkCallback(
                    new NetworkRequest.Builder()
                            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                            .build(), connectivityCallback);
            monitoringConnectivity = true;
        }

    }

我们的所有工作几乎都完成了,我们只需要在Activity/Fragment的onResume()方法中调用checkConnectivity()方法即可。

  @Override
    protected void onResume() {
        super.onResume();
        checkConnectivity();
    }

*在 Activity/Fragment 的 onPause() 方法中取消注册 NetworkCallback*

   @Override
    protected void onPause() {
        // if network is being moniterd then we will unregister the network callback
        if (monitoringConnectivity) {
            final ConnectivityManager connectivityManager
                    = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            connectivityManager.unregisterNetworkCallback(connectivityCallback);
            monitoringConnectivity = false;
        }
        super.onPause();
    }

就这样,在你需要监视网络的Activity/Fragment的每个类中添加此代码!不要忘记取消注册!!!


1
我注意到当用户切换网络(例如从Wi-Fi切换到蜂窝数据),onAvailable()方法首先被调用以表示蜂窝数据已连接,然后onLost()方法被调用以表示Wi-Fi已断开连接。因此,应用程序会表现得好像没有网络一样。你有解决办法吗? - katie
1
在onLost()方法中执行代码之前尝试添加一些延迟。5或10秒的延迟应该足够了。如果这不起作用,请查看我的无网络连接库https://github.com/vasu-bhardwaj/NoInternet。此库使用可观察设计模式。 - hermes
1
我还注意到这段代码无法覆盖WIFI已连接但没有可用互联网的情况。我们如何克服这种情况,避免常规ping? - Min2

3
创建一个继承自BroadcastReceiver的类,使用ConnectivityManager.EXTRA_NO_CONNECTIVITY来获取连接信息。
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.widget.Toast;

public class CheckConnectivity extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent arg1) {

    boolean isConnected = arg1.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
    if(isConnected){
        Toast.makeText(context, "Internet Connection Lost", Toast.LENGTH_LONG).show();
    }
    else{
        Toast.makeText(context, "Internet Connected", Toast.LENGTH_LONG).show();
    }
   }
 }

请在 manifest 文件中添加此权限。
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.INTERNET" />

不好的想法!使用服务来进行网络检查,然后从BroadcastReceiver中提取它。 - olajide

1

ConnectivityObserver.kt:

package com.example.checkInternet

import kotlinx.coroutines.flow.Flow

interface ConnectivityObserver {

    fun observe(): Flow<Status>

    enum class Status {
        Available, Unavailable, Losing, Lost
    }
}

NetworkConnectivityObserver.kt:

package com.example.checkInternet

import android.content.Context
import android.net.*
import android.os.Build
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch


@OptIn(ExperimentalCoroutinesApi::class)
class NetworkConnectivityObserver(
    context: Context,
): ConnectivityObserver {

    private val connectivityManager =
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    private val networkRequest = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .build()

    override fun observe(): Flow<ConnectivityObserver.Status> {
        return callbackFlow {
            val callback = object : ConnectivityManager.NetworkCallback() {
                override fun onAvailable(network: Network) {
                    super.onAvailable(network)
                    launch { send(ConnectivityObserver.Status.Available) }
                }

                override fun onLosing(network: Network, maxMsToLive: Int) {
                    super.onLosing(network, maxMsToLive)
                    launch { send(ConnectivityObserver.Status.Losing) }
                }

                override fun onLost(network: Network) {
                    super.onLost(network)
                    launch { send(ConnectivityObserver.Status.Lost) }
                }

                override fun onUnavailable() {
                    super.onUnavailable()
                    launch { send(ConnectivityObserver.Status.Unavailable) }
                }
            }

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                connectivityManager.registerDefaultNetworkCallback(callback)
            }else{
                connectivityManager.registerNetworkCallback(networkRequest, callback)
            }
            awaitClose {
                connectivityManager.unregisterNetworkCallback(callback)
            }
        }.distinctUntilChanged()
    }
}

MainActivity.kt

package com.example.checkInternet

import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.example.checkInternet.ConnectivityObserver
import com.example.checkInternet.NetworkConnectivityObserver
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {

    private val connectivityObserver : NetworkConnectivityObserver by lazy {
        NetworkConnectivityObserver(this)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView( R.layout.activity_main)

        lifecycleScope.launch {
            connectivityObserver.observe().collect {
                when (it) {
                    ConnectivityObserver.Status.Available -> {
                      Toast.makeText(this@MainActivity,"Network Available",Toast.LENGTH_LONG).show()
                    }
                    ConnectivityObserver.Status.Unavailable -> {
                        Toast.makeText(this@MainActivity,"Network Unavailable",Toast.LENGTH_LONG).show()
                    }
                    ConnectivityObserver.Status.Losing -> {
                        Toast.makeText(this@MainActivity,"Network Losing",Toast.LENGTH_LONG).show()
                    }
                    ConnectivityObserver.Status.Lost -> {
                        Toast.makeText(this@MainActivity,"Network Lost",Toast.LENGTH_LONG).show()

                    }
                }
            }
        }

    }

}



1
在Activity或Fragment中。
public static final String BROADCAST = "checkinternet";
IntentFilter intentFilter;

在onCreate内部
   intentFilter = new IntentFilter();
   intentFilter.addAction(BROADCAST);
   Intent serviceIntent = new Intent(this,Networkservice.class);
   startService(serviceIntent);
   if (Networkservice.isOnline(getApplicationContext())){
       Toast.makeText(getApplicationContext(),"true",Toast.LENGTH_SHORT).show();
   }else
       Toast.makeText(getApplicationContext(),"false",Toast.LENGTH_SHORT).show();

在onCreate之外

 public BroadcastReceiver broadcastReceiver=new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(BROADCAST)){
            if (intent.getStringExtra("online_status").equals("true")){
                Toast.makeText(getApplicationContext(),"true",Toast.LENGTH_SHORT).show();
                Log.d("data","true");
            }else {
                Toast.makeText(getApplicationContext(), "false", Toast.LENGTH_SHORT).show();
                Log.d("data", "false");
            }
        }
    }
};

@Override
protected void onRestart() {
    super.onRestart();
    registerReceiver(broadcastReceiver,intentFilter);
}

@Override
protected void onPause() {
    super.onPause();
    unregisterReceiver(broadcastReceiver);
}

@Override
protected void onResume() {
    super.onResume();
    registerReceiver(broadcastReceiver,intentFilter);
}

//类

public class Networkservice extends Service {

@Override
public void onCreate() {
    super.onCreate();
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    handler.post(perioud);
    return START_STICKY;
}
public static boolean isOnline(Context context){
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo nf=cm.getActiveNetworkInfo();
    if (nf!=null&&nf.isConnectedOrConnecting())
        return true;
        else
            return false;
}
Handler handler=new Handler();
private Runnable perioud =new Runnable() {
    @Override
    public void run() {
        handler.postDelayed(perioud,1*1000- SystemClock.elapsedRealtime()%1000);

        Intent intent = new Intent();
        intent.setAction(MainActivity.BROADCAST);
        intent.putExtra("online_status",""+isOnline(Networkservice.this));
        sendBroadcast(intent);
    }
};
}

0

您也可以尝试使用Class服务。只需设置以秒为单位的时间间隔和要ping的url:

Android检查互联网连接

只需记得将服务添加到清单文件中,并添加权限即可。


0

Android系统已经为您做了这件事。注册BroadcastReceiver以侦听WiFi和网络状态的更改,并处理系统发送的Intent,当WiFi或网络状态发生变化时。

请查看this question以获取更多信息。

一旦您注册了BroadcastReceiver,网络状态更改侦听将在后台(在操作系统中)进行,并且当网络状态更改时,Intent将通过UI线程(最可能)发送到您的接收器。如果您想在后台线程上接收Intent,请查看this question以获取更多信息。


0
要检查互联网连接,只需注册广播以获取CONNECTIVITY_CHANGEWIFI_STATE_CHANGED。因此,每当互联网连接或断开连接时,我们的BroadcastReceiver的onReceive方法会被调用,在那里我们可以编写我们的逻辑。
在AndroidManifest.xml中。
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
     <receiver
            android:name="NetworkChangeReceiver"
            android:label="NetworkChangeReceiver" >
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
                <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
            </intent-filter>
        </receiver>

在NetworkChangeReceiver类中。

 public class NetworkChangeReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(final Context context, final Intent intent) {
    
            int status = NetworkUtil.getConnectivityStatusString(context);
            if ("android.net.conn.CONNECTIVITY_CHANGE".equals(intent.getAction())) {
                if (status == NetworkUtil.NETWORK_STATUS_NOT_CONNECTED) {
                 
                  //write code for internet is disconnected...

                } else {

                   //write code for internet is connected...

                }
           }
        }
    }

检查互联网的状态。

 public class NetworkUtil {
    public static final int TYPE_NOT_CONNECTED = 0;
        public static final int TYPE_WIFI = 1;
        public static final int TYPE_MOBILE = 2;
        public static final int NETWORK_STATUS_NOT_CONNECTED = 3;
        public static final int NETWORK_STATUS_WIFI = 4;
        public static final int NETWORK_STATUS_MOBILE = 5;
    
        public static int getConnectivityStatus(Context context) {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            if (null != activeNetwork) {
                if(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI)
                    return TYPE_WIFI;
    
                if(activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE)
                    return TYPE_MOBILE;
            } 
            return TYPE_NOT_CONNECTED;
        }
    
        public static int getConnectivityStatusString(Context context) {
            int conn = NetworkUtil.getConnectivityStatus(context);
            int status = 0;
            if (conn == NetworkUtil.TYPE_WIFI) {
                status = NETWORK_STATUS_WIFI;
            } else if (conn == NetworkUtil.TYPE_MOBILE) {
                status = NETWORK_STATUS_MOBILE;
            } else if (conn == NetworkUtil.TYPE_NOT_CONNECTED) {
                status = NETWORK_STATUS_NOT_CONNECTED;
            }
            return status;
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接