25

我正在开发一个将持续保持连接到 Internet 的 Android 应用程序。如果互联网中断,它应该给用户一个适当的消息。

有没有类似 Internet Listener 的东西?或者如何实现这个事件,只要互联网连接不可用,它就会发出警报。

4

2 回答 2

50

为此创建一个广播接收器并将其注册到清单文件中。

首先创建一个新类NetworkStateReceiver并扩展 BroadcastReceiver。

public class NetworkStateReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
     Log.d("app","Network connectivity change");
     if(intent.getExtras()!=null) {
        NetworkInfo ni=(NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
        if(ni!=null && ni.getState()==NetworkInfo.State.CONNECTED) {
            Log.i("app","Network "+ni.getTypeName()+" connected");
        }
     }
     if(intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY,Boolean.FALSE)) {
            Log.d("app","There's no network connectivity");
     }
   }
}

将此代码放在“application”元素下的 AndroidManifest.xml 中:

<receiver android:name=".NetworkStateReceiver">
   <intent-filter>
      <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
   </intent-filter>
</receiver>

并添加此权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

编辑

此代码仅检测连接更改,但无法判断其连接的网络是否可以访问 Internet。使用此方法检查 -

public static boolean hasActiveInternetConnection(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
            urlc.setRequestProperty("User-Agent", "Test");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 200);
        } catch (IOException e) {
        Log.e(LOG_TAG, "Error checking internet connection", e);
        }
    } else {
    Log.d(LOG_TAG, "No network available!");
    }
    return false;
}
于 2012-08-28T10:16:01.297 回答
5

上面 Chirag Raval 的代码确实有效。问题是即使应用程序没有在前台运行,侦听器也会被调用。

恕我直言,更好的方法是在所有应用程序活动的onResume()/方法中注册/注销接收器。onPause()这段代码应该这样做:

private final NetworkStateReceiver stateReceiver = new NetworkStateReceiver();

@Override
protected void onResume() {
    super.onResume();
    IntentFilter filter = new IntentFilter();
    filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
    registerReceiver(stateReceiver, filter);
}

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

显然,从AndroidManifest.xml文件中删除注册。

使用此解决方案,在您的应用程序的活动之间切换时也会调用接收器(假设您正在关闭它们)。在这种情况下,请使用静态标志(在所有活动之间共享),如下例所示(称为online):

public class NetworkStateReceiver extends BroadcastReceiver {

    private static boolean online = true;  // we expect the app being online when starting

    public static final String TAG = NetworkStateReceiver.class.getSimpleName();

    public void onReceive(Context context, Intent intent) {
        Log.d(TAG,"Network connectivity change");
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo ni = manager.getActiveNetworkInfo();
        if (ni == null || ni.getState() != NetworkInfo.State.CONNECTED) {
            Log.d(TAG,"There's no network connectivity");
            if (online) // don't show the message if already offline
                Toast.makeText(context, R.string.noInternet, Toast.LENGTH_SHORT).show();
            online = false;
        } else {
            Log.d(TAG,"Network "+ni.getTypeName()+" connected");
            if (!online)  // don't show the message if already online
                Toast.makeText(context, R.string.backOnline, Toast.LENGTH_SHORT).show();
            online = true;
        }
    }
}

如果在离线时启动您的应用程序,则会出现 Toast 消息;否则只有在丢失/重新建立连接时才会出现。

于 2017-04-04T11:19:47.917 回答