Android:互联网连接改变监听器

Con*_*use 51 java android connectivity

我已经有了这个代码来监听连接变化 -

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");
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我使用此代码检查Internet连接 - Internet Check

但问题是,如果网络在没有任何连接变化的情况下突然失去互联网连接,则此代码无用.有没有办法为Internet连接更改创建Broadcast Receiver侦听?我有一个Web应用程序,突然的Internet连接更改可能会导致问题.

Cja*_*mes 77

试试这个

public class NetworkUtil {
    public static final int TYPE_WIFI = 1;
    public static final int TYPE_MOBILE = 2;
    public static final int TYPE_NOT_CONNECTED = 0;
    public static final int NETWORK_STATUS_NOT_CONNECTED = 0;
    public static final int NETWORK_STATUS_WIFI = 1;
    public static final int NETWORK_STATUS_MOBILE = 2;

    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;
    }
}
Run Code Online (Sandbox Code Playgroud)

而对于BroadcastReceiver

public class NetworkChangeReceiver extends BroadcastReceiver {

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

        int status = NetworkUtil.getConnectivityStatusString(context);
        Log.e("Sulod sa network reciever", "Sulod sa network reciever");
        if ("android.net.conn.CONNECTIVITY_CHANGE".equals(intent.getAction())) {
            if (status == NetworkUtil.NETWORK_STATUS_NOT_CONNECTED) {
                new ForceExitPause(context).execute();
            } else {
                new ResumeForceExitPause(context).execute();
            }
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

不要忘记将它放入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>
Run Code Online (Sandbox Code Playgroud)

希望这会帮助你干杯!

  • 在您的Manifest中注册这样的接收器以接收连接更改事件将不再适用于Android 7.0+ https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html#MonitorChanges (28认同)
  • 为什么你需要检查是否(!"android.intent.action.BOOT_COMPLETED".equals(intent.getAction()))???? (8认同)
  • 它在 gionee 的 plus 设备中不起作用......还有其他方法可以做到这一点吗? (2认同)
  • 除了一个问题外,这很有效。我还试图让 LAN/以太网连接到我的 Android 电视盒的侦听器。这适用于 WiFi 或移动连接,但不适用于 LAN 连接。我有这个检查 LAN 连接状态的代码,但我需要一个监听器来捕捉互联网状态的任何变化,而不仅仅是 WiFi 或移动网络:`code` NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); boolean isConnected = activeNetwork != null &amp;&amp; activeNetwork.isConnectedOrConnecting(); `代码` (2认同)
  • 发现一个网络连接的特殊情况,说没有互联网,但实际上有。事实证明,当电池电量低且应用程序刚刚切换时网络发生变化且应用程序刚刚切换时,在特定情况下,“getActiveNetworkInfo”将始终返回您 **DISCONNECTED/BLOCKED** 查看这篇文章:/sf/ 34884442/android-checking-network-connectivity-return-not-connected-when-connected-to-wi/45231746#45231746 (2认同)

alg*_*rid 38

这是使用registerDefaultNetworkCallback(和registerNetworkCallbackAPI < 24)的 Java 代码:

ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        // network available
    }

    @Override
    public void onLost(Network network) {
        // network unavailable
    }
};

ConnectivityManager connectivityManager =
        (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    connectivityManager.registerDefaultNetworkCallback(networkCallback);
} else {
    NetworkRequest request = new NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
    connectivityManager.registerNetworkCallback(request, networkCallback);
}
Run Code Online (Sandbox Code Playgroud)

  • `NetworkRequest` 需要最低 API 级别 21。对于 API 级别 19 我们能做什么? (3认同)

Sil*_*a H 32

更新:

针对Android 7.0(API级别24)及更高版本的应用如果在其清单中声明广播接收器,则不会收到CONNECTIVITY_ACTION广播.如果应用程序使用Context.registerReceiver()注册其BroadcastReceiver并且该上下文仍然有效,它们仍将接收CONNECTIVITY_ACTION广播.

您需要通过以下registerReceiver()方法注册接收器:

 IntentFilter intentFilter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
 mCtx.registerReceiver(new NetworkBroadcastReceiver(), intentFilter);
Run Code Online (Sandbox Code Playgroud)


bmj*_*hns 23

api 28+中已弃用 ConnectivityAction 。相反registerDefaultNetworkCallback,只要支持api 24+,就可以使用。

在科特林:

val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager?.let {
    it.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            //take action when network connection is gained
        }
        override fun onLost(network: Network?) {
            //take action when network connection is lost
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

  • 就 2019-2020 年而言,“调用需要 API 级别 24”仍然很大 (5认同)
  • 正确的 !!这是 2019 年最有效的答案:) (3认同)
  • 当我们只有单一连接(即移动数据或 Wifi)时,这可以正常工作。但是,当我同时使用两者并关闭其中一个时,它也会触发 onLost() 而我有互联网连接。您知道为什么会发生这种情况吗?或者我们该如何处理这种情况? (3认同)

Man*_*ger 16

这应该工作:

public class ConnectivityChangeActivity extends Activity {

    private BroadcastReceiver networkChangeReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d("app","Network connectivity change");
        }
    };

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

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(networkChangeReceiver, intentFilter);
    }

    @Override
    protected void onPause() {
        super.onPause();

        unregisterReceiver(networkChangeReceiver);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!!几行中最简单的解决方案 (2认同)

Lak*_*hna 6

我将此方法用作连接侦听器。为 Lolipop+ 工作,Android JAVA 语言。

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkRequest networkRequest = new NetworkRequest.Builder().build();
    connectivityManager.registerNetworkCallback(networkRequest, new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            super.onAvailable(network);
            Log.i("Tag", "active connection");
        }

        @Override
        public void onLost(Network network) {
            super.onLost(network);
            Log.i("Tag", "losing active connection");
            isNetworkConnected();
        }
    });
}

private boolean isNetworkConnected() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    if (!(cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected())) {
        //Do something
        return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

并在您的 Android Manifest.xml 中添加此权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Run Code Online (Sandbox Code Playgroud)

  • 根据一位评论者的说法:“当我们只有单一连接(即移动数据或 Wifi)时,这工作得很好。但是当我同时使用这两种连接并关闭其中一个时,它也会触发 onLost(),而我有互联网连接。”猜测是名为 isNetworConnected 的代码的第二部分防止误报? (2认同)
  • @Delark,就我而言,如果手机同时连接到两者,则仅当 wifi 关闭时才调用 `onLost()` 。只要 wifi 开启,移动数据状态改变就不会触发回调。Pixel 3a XL,安卓 12。 (2认同)
  • 谢谢@Sam,我的待办事项列表中遇到了一些问题,我认为这与流上的一些并发问题有关,但现在我想了一下,这很可能是因为我的 wifi 造成的问题有时会断开连接,我认为它也可能出现在仅与 wifi 连接的非 SIM 设备中,因为我尝试重新连接到 wifi(应该工作正常),并且没有任何反应发生,并且监听器重新连接很困难(取消注册然后注册)是必需的。 (2认同)
  • @Sam BTW 不要忘记同步布尔输出,因为在 200 Millis 回调“分派”错误之前,重新连接可能会变为 true。 (2认同)

Ale*_*ber 6

在我的自定义视图模型中,我观察到网络状态变化如下:

public class MyViewModel extends AndroidViewModel {
    private final MutableLiveData<Boolean> mConnected = new MutableLiveData<>();

    public MyViewModel(Application app) {
        super(app);

        ConnectivityManager manager = (ConnectivityManager)app.getSystemService(Context.CONNECTIVITY_SERVICE);

        if (manager == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            mConnected.setValue(true);
            return;
        }

        NetworkRequest networkRequest = new NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
            .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
            .build();

        manager.registerNetworkCallback(networkRequest, new ConnectivityManager.NetworkCallback() {
            Set<Network> availableNetworks = new HashSet<>();

            public void onAvailable(@NonNull Network network) {
                availableNetworks.add(network);
                mConnected.postValue(!availableNetworks.isEmpty());
            }

            public void onLost(@NonNull Network network) {
                availableNetworks.remove(network);
                mConnected.postValue(!availableNetworks.isEmpty());
            }

            public void onUnavailable() {
                availableNetworks.clear();
                mConnected.postValue(!availableNetworks.isEmpty());
            }
        });
    }

    @NonNull
    public MutableLiveData<Boolean> getConnected() {
        return mConnected;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在我的 Activity 或 Fragment 中,我可以通过观察来更改 UI:

@Override
protected void onCreate(Bundle savedInstanceState) {
    MyViewModel vm = new ViewModelProvider(this).get(MyViewModel.class);

    vm.getConnected().observe(this, connected -> {
        // TODO change GUI depending on the connected value
    });
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

78101 次

最近记录:

5 年,10 月 前