【问题标题】:Android: Checking network connectivity return not connected when connected to wifi/3g in Broadcast receiverAndroid:在广播接收器中连接到 wifi/3g 时检查网络连接返回未连接
【发布时间】:2016-04-25 09:04:22
【问题描述】:

我想在广播接收器中检查设备是否已连接。 以下是我的代码:

public boolean isOnline(Context context) {
NetworkInfo info = (NetworkInfo) ((ConnectivityManager) context
        .getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();

if (info == null || !info.isConnected()) {
    Log.e("UpdateDataReceiver","info: "+info);
    return false;
}
return true;
}

我的代码有问题: 当 BroadcastReceiver 在后台触发时(当应用程序在后台时),上面的函数返回 false(即使连接了 wifi) 当应用在前台时返回true。

信息:NetworkInfo:类型:WIFI[],状态:DISCONNECTED/BLOCKED,原因: (未指定),额外:(无),漫游:假,故障转移:假, isAvailable: true, isConnectedToProvisioningNetwork: false, simId: 0

设备信息:Redmi Note

【问题讨论】:

  • 也许你应该扩展 WakefulBroadcastReceiver
  • 似乎 BLOCKED 可能意味着断电以节省电池。我在这种状态下尝试了一个网络请求,它确实通过了,但延迟比正常情况要长。
  • 我遇到了同样的问题,并在 Google 的问题跟踪器上发现了一个似乎适合的问题:issuetracker.google.com/issues/37137911 作为快速修复,我使用了stackoverflow.com/a/45231746/1394330 中提到的类似的后备解决方案/跨度>

标签: android


【解决方案1】:

这就是我处理它的方式,因为即使有网络连接,getActiveNetworkInfo 在特定情况下总是会返回给你 DISCONNECTED/BLOCKED。这是BroadcastReceiver 中的接收方法,意图为filter ConnectivityManager.CONNECTIVITY_ACTION

@Override
public void onReceive(Context context, Intent intent) {
    ConnectivityManager conn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = conn.getActiveNetworkInfo();

    NetworkInfo intentNetworkInfo = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);

    if (intentNetworkInfo == null) {
        intentNetworkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    }

    if (networkInfo == null) {
        networkInfo = intentNetworkInfo;
    } else {
        //when low battery get ActiveNetwork might receive DISCONNECTED/BLOCKED but the intent data is actually CONNECTED/CONNECTED
        if (intentNetworkInfo != null && networkInfo.isConnectedOrConnecting() != intentNetworkInfo.isConnectedOrConnecting()) {
            networkInfo = intentNetworkInfo;
        }
    }

    //do something with networkInfo object
}

我已经寻找更好的解决方案,但没有结果。我能够在我的设备(Pixel 7.1.2)上 100% 重现的情况如下:

  • 设备的电池电量必须低于 15%(其他设备
  • Wifi 已开启,应用已启动
  • 将应用发送到后台关闭 wifi 并转到 3g(反之亦然)
  • 返回应用程序
  • 在这种情况下,应用程序将从getActiveNetworkInfo 报告已断开/已阻止。

如果您在应用程序中更改连接,则可以,但如果它在后台,则不会。这不会在您调试时发生,因为即使电池电量不足,它也会为设备充电。

在上面的示例中,ConnectivityManager 和 WifiManager 中的 EXTRA_NETWORK_INFO 实际上是相同的字符串“networkInfo”,但如果在其他 Android 版本中它们不同,我不想冒险,所以它是额外的样板。

您可以直接使用意图中的 networkInfo,但我想在这里说明实际网络信息不是实际网络信息的情况。

【讨论】:

  • 在节电模式开启的 Nexus 6p 和三星 S8 上遇到同样的问题。有趣的是,即使在从 ConnectivityManager.EXTRA_NETWORK_INFO 正确显示 CONNECTED 的 NetworkInfo 充电时,三星 S8 仍处于节电状态,但自 API 16 起已弃用。我不确定是否要使用它。
  • 在上面的例子中是为了向后兼容,WifiManager“networkInfo”的字符串是相同的。
  • ConnectivityManager.EXTRA_NETWORK_INFO - 自 API 16 起已弃用。
【解决方案2】:

我相信你可以做到这一点,

使用 ConnectivityManger.Connectivity_Action 的 IntentFilter 注册广播接收器

private BroadcastReceiver receiverDataChange;

private void registerData(){

    try {
        receiverDataChange = new bcr_ToggleData();
        IntentFilter filterData = new IntentFilter();
        filterData.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(receiverDataChange, filterData);

    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    }}

然后在你的广播接收器类中

public class bcr_ToggleData extends BroadcastReceiver {


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

    String action = intent.getAction();

    if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {

        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        int state = telephonyManager.getDataState();
        switch (state){

            case TelephonyManager.DATA_DISCONNECTED: // off
                Log.d("DavidJ", "DISCONNECTED");
                break;

            case TelephonyManager.DATA_CONNECTED: // on
                Log.d("DavidJ", "CONNECTED");
                break;
        }
    }
}

}

当您进入设置并打开/关闭移动数据时,它会触发。

希望这会有所帮助! :)

【讨论】:

    【解决方案3】:
        ConnectivityManager cm =
            (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    boolean isConnected = activeNetwork != null &&
                          activeNetwork.isConnectedOrConnecting();
    

    我在这个谷歌教程上找到了这个:http://developer.android.com/intl/pt-br/training/monitoring-device-state/connectivity-monitoring.html。看看吧。

    【讨论】:

      猜你喜欢
      • 2017-07-17
      • 1970-01-01
      • 1970-01-01
      • 2020-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多