【问题标题】:Android getAllNetworkInfo() is Deprecated. What is the alternative?Android getAllNetworkInfo() 已弃用。什么是替代方案?
【发布时间】:2015-11-21 10:09:26
【问题描述】:

我想使用ConnectivityManager 提供getAllNetworkInfo() 方法来检查Android 中的网络可用性。此方法在 API 级别 23 中已弃用。开发人员文档建议改用getAllNetworks()。我尝试过,但无法从旧代码中获得确切的功能。请有人指导我如何使用getAllNetworks() 方法?

 public boolean isConnectingToInternet(){
    ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
      if (connectivity != null) 
      {
          @SuppressWarnings("deprecation")
        NetworkInfo[] info = connectivity.getAllNetworkInfo();
          //use getAllNetworks() instead
          if (info != null) 
              for (int i = 0; i < info.length; i++) 
                  if (info[i].getState() == NetworkInfo.State.CONNECTED)
                  {
                      return true;
                  }
      }
      return false;
}

【问题讨论】:

标签: android networking android-6.0-marshmallow


【解决方案1】:

当我更新已弃用的代码但仍想支持向后 Api 时。我用这个:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.WANTED API VERSION){
//code
}else{
//code
}

通过这种方式,每个设备都为其使用适当的代码。 示例:

public class ConnectionDetector {

    private Context mContext;

    public ConnectionDetector(Context context) {
        this.mContext = context;
    }
    /**
     * Checking for all possible internet providers
     * **/
    public boolean isConnectingToInternet() {
        ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Network[] networks = connectivityManager.getAllNetworks();
            NetworkInfo networkInfo;
            for (Network mNetwork : networks) {
                networkInfo = connectivityManager.getNetworkInfo(mNetwork);
                if (networkInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
                    return true;
                }
            }
        }else {
            if (connectivityManager != null) {
                //noinspection deprecation
                NetworkInfo[] info = connectivityManager.getAllNetworkInfo();
                if (info != null) {
                    for (NetworkInfo anInfo : info) {
                        if (anInfo.getState() == NetworkInfo.State.CONNECTED) {
                            LogUtils.d("Network",
                                    "NETWORKNAME: " + anInfo.getTypeName());
                            return true;
                        }
                    }
                }
            }
        }
        Toast.makeText(mContext,mContext.getString(R.string.please_connect_to_internet),Toast.LENGTH_SHORT).show();
        return false;
    }
}

【讨论】:

【解决方案2】:

我已经制作了可以帮助您检查的实用程序:

  • 如果网络已连接。
  • 如果已连接 WiFi。
  • 如果移动数据已连接。

它根据运行平台使用旧 API 或新 API:

import android.annotation.TargetApi;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.os.Build;
import android.support.annotation.NonNull;

public class NetworkUtils {

    public static boolean isConnected(@NonNull Context context) {
        ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
        return (networkInfo != null && networkInfo.isConnected());
    }

    public static boolean isWifiConnected(@NonNull Context context) {
        return isConnected(context, ConnectivityManager.TYPE_WIFI);
    }

    public static boolean isMobileConnected(@NonNull Context context) {
        return isConnected(context, ConnectivityManager.TYPE_MOBILE);
    }

    private static boolean isConnected(@NonNull Context context, int type) {
        ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            NetworkInfo networkInfo = connMgr.getNetworkInfo(type);
            return networkInfo != null && networkInfo.isConnected();
        } else {
            return isConnected(connMgr, type);
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static boolean isConnected(@NonNull ConnectivityManager connMgr, int type) {
        Network[] networks = connMgr.getAllNetworks();
        NetworkInfo networkInfo;
        for (Network mNetwork : networks) {
            networkInfo = connMgr.getNetworkInfo(mNetwork);
            if (networkInfo != null && networkInfo.getType() == type && networkInfo.isConnected()) {
                return true;
            }
        }
        return false;
    }

}

更新:
有关@TargetApi@RequiresApi 的更多信息: https://stackoverflow.com/a/40008157/421467 https://developer.android.com/reference/kotlin/androidx/annotation/RequiresApi

【讨论】:

  • 请记住,在一些奇怪的设备上:connMgr.getNetworkInfo(mNetwork) 可能会抛出 NullPointerExcecption。今天发生在我身上,似乎是由 IConnectivityManager 内的本机方法抛出的。解决方法是在你的 for 循环中尝试/捕获它,并决定回退到这个特定网络的不推荐使用的方法。
  • @MariusC 感谢您的回复,请将崩溃的堆栈跟踪发送到 gmail.com 的 yakiv.mospan。将 Nullpointer 包装在 try-catch 中是非常糟糕的做法。我们也需要避免 Nullpointer 本身。也许mNetwork有问题,也许那个奇怪的设备不支持getAllNetwokrs返回的某些网络?
  • @MariusC 顺便说一句,它是什么设备,它在其他设备上工作,你确定你有权限ACCESS_NETWORK_STATE 吗?
  • 嗨 Yakiv,请在下面找到我在 Android 框架项目上打开的与该错误相关的票:github.com/android/platform_frameworks_base/issues/123
  • 另外...我知道抓住它是一种不好的做法,而且这是一个丑陋的解决方法,但到目前为止,这是我能做的最好的事情,你无法避免这种情况,因为正在发生随机,您不能在 Network 实例上提供任何信息来避免这种情况。
【解决方案3】:

如果有人需要 Kotlin 版本,(下面是与 Maor Hadad 相同的代码)

fun Context.isNetworkConnected(): Boolean {
  val manager = getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    val allNetworks = manager?.allNetworks?.let { it } ?: return false
    allNetworks.forEach { network ->
      val info = manager.getNetworkInfo(network)
      if (info.state == NetworkInfo.State.CONNECTED) return true
    }
  } else {
    val allNetworkInfo = manager?.allNetworkInfo?.let { it } ?: return false
    allNetworkInfo.forEach { info ->
      if (info.state == NetworkInfo.State.CONNECTED) return true
    }
  }
  return false
}

此代码是 Context 的扩展方法。

在任何kotlin文件(.kt)中写下这段代码,然后你就可以在任何实现了Context的类(如Activity)中使用该方法。

【讨论】:

  • 这是一个更实用的方法return manager.allNetworks.any { NetworkInfo.State.CONNECTED == manager.getNetworkInfo(it).state }。但是,这并不能解决问题,因为NetworkInfo.html#getstate已弃用
【解决方案4】:

试试下面的代码:

ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);    
    Network[] networks = connectivityManager.getAllNetworks();
    NetworkInfo networkInfo;
    Network network;
        for (int i = 0; i < networks.length; i++){               
            network = networks[i];
            networkInfo = connectivityManager.getNetworkInfo(network);
            if ((networkInfo.getType() ==     ConnectivityManager.TYPE_WIFI) && (networkInfo.getState().equals(NetworkInfo.State.CONNECTED))) {
               ConnectivityManager.setProcessDefaultNetwork(network);
                break;
            }
        }

【讨论】:

  • 感谢您的回答。但是,这里不推荐使用 setProcessDefaultNetwork()
  • connectivityManager.getAllNetworks() 和 connectivityManager.getNetworkInfo(network) 需要 API 21
【解决方案5】:

试试这个

ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
Network[] networks = cm.getAllNetworks();
if (cm != null) {
    for (Network netinfo : networks) {
        NetworkInfo ni = cm.getNetworkInfo(netinfo);
        if (ni.isConnected() && ni.isAvailable()) {
                connected = true;
            }
        }
    }

【讨论】:

  • 该问题表明NetworkInfo 已折旧,因此这不会回答有关替代方案的问题。
【解决方案6】:

试试这个。这是最简单的方法。

public static boolean isNetworkAvailable(Activity activity) {  
        ConnectivityManager connectivity = (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);  
        if (connectivity == null) {  
            return false;  
        } else {  
            NetworkInfo[] info = connectivity.getAllNetworkInfo();  
            if (info != null) {  
                for (int i = 0; i < info.length; i++) {  
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {  
                        return true;  
                    }  
                }  
            }  
        }  
        return false;  
    }  
}  

【讨论】:

  • 再一次,问题询问NetworkInfo 的替代方案是什么......显然没有人(无论如何在这里)阅读问题和/或可以提供答案。当一个人在寻找答案时会感到沮丧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-11
  • 2016-08-16
  • 2023-03-13
  • 2022-10-05
相关资源
最近更新 更多