Android的getAllNetworkInfo()已经被弃用,有什么替代品?

30

我想使用ConnectivityManager来检查Android中网络的可用性,它提供了getAllNetworkInfo()方法。但是这个方法在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;
}

连接管理器 getNetworkInfo(int) 已弃用 - 答案在这里:https://dev59.com/NFwY5IYBdhLWcg3wgX-V - Shirish Herwade
6个回答

31

当我更新过时的代码,但仍希望支持向后兼容的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;
    }
}

1
请注意,NetworkInfo#getState也已经被弃用 - JJD

14

我已经制作了一些实用工具,可以帮助您检查:

  • 网络是否连接。
  • WiFi是否连接。
  • 移动数据是否连接。

它根据运行平台使用旧版或新版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://dev59.com/OFkS5IYBdhLWcg3wV1Zy#40008157 https://developer.android.com/reference/kotlin/androidx/annotation/RequiresApi


请注意,在某些奇怪的设备上,connMgr.getNetworkInfo(mNetwork)可能会抛出NullPointerExcecption异常。今天我遇到了这种情况,似乎是由IConnectivityManager内部的本地方法引起的。解决方法是在您的_for_循环中尝试/捕获此异常,并决定回退到特定网络的已弃用方法。 - Marius Constantin
@MariusC 谢谢您的回复,请将崩溃的堆栈跟踪发送给我,我的邮箱是yakiv.mospan@gmail.com。在try-catch中包装Nullpointer是非常糟糕的做法,我们需要避免Nullpointer本身。也许mNetwork出了问题,或者那个奇怪的设备不支持getAllNetwokrs返回的某些网络? - Yakiv Mospan
@MariusC 顺便问一下,这是什么设备?它在其他设备上工作吗?你确定你有ACCESS_NETWORK_STATE权限吗? - Yakiv Mospan
嗨Yakiv,以下是我在Android Framework Project上针对该错误开启的工单链接:https://github.com/android/platform_frameworks_base/issues/123 - Marius Constantin
1
此外...我知道捕获它是一种不好的做法,这是一个丑陋的解决方法,但到目前为止,这是我能做的最好的事情,因为它是随机发生的,你无法在网络实例上获取任何信息来避免它。 - Marius Constantin
@YakivMospan这个问题表明NetworkInfo#isConnectedOrConnecting可能被调用,但它已经过时了。在这种情况下,您的方法并没有提供一种解决方法。 - JJD

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也已经被弃用了。 - JJD

2

试试这个

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;
            }
        }
    }

1
这个问题表明NetworkInfo已经过时,因此这并不能回答关于替代方案的问题。 - Prescott Chartier

2

试试以下代码:

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;
            }
        }

2
谢谢回答。但是,setProcessDefaultNetwork()已经被弃用了。 - Anees U
2
connectivityManager.getAllNetworks()和connectivityManager.getNetworkInfo(network)需要API 21以上版本。 - Olcay Ertaş

-2

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

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的替代方案是什么......显然没有人(至少在这里)读懂问题或者能够提供答案。当一个人正在寻找答案时,这种情况非常令人沮丧。 - Prescott Chartier

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