Android getAllNetworkInfo() 已弃用。啥是替代方案?

Posted

技术标签:

【中文标题】Android getAllNetworkInfo() 已弃用。啥是替代方案?【英文标题】: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;

【问题讨论】:

ConnectivityManager getNetworkInfo(int) deprecated的可能重复 在这里回答 - ***.com/questions/32547006/… 【参考方案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;
    

【讨论】:

你所有的设备都是男性吗? :O ;-) 请注意,NetworkInfo#getState 也已弃用【参考方案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://***.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 的替代方案是什么......显然没有人(无论如何在这里)阅读问题和/或可以提供答案。当一个人在寻找答案时会感到沮丧。

以上是关于Android getAllNetworkInfo() 已弃用。啥是替代方案?的主要内容,如果未能解决你的问题,请参考以下文章

Android逆向系列文章— Android基础逆向

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

android 21 是啥版本

Android逆向-Android基础逆向(2-2)

【Android笔记】android Toast