如何检查移动网络是否已启用/禁用

5
我想知道移动网络是否已启用或禁用。
我的应用程序旨在帮助用户接听电话时使用互联网。因此,如果Wi-Fi具有休眠策略并且移动网络已禁用,我希望在用户第一次访问应用程序时显示信息框(在手机开始响铃后的毫秒内需要互联网)。
我找到了Settings.System.WIFI_SLEEP_POLICY,但找不到任何关于如何检查移动网络是否禁用(当Wi-Fi处于打开和工作状态时)的信息。
如有帮助,将不胜感激!
编辑: 问题是我想知道用户是否关闭了移动网络(而手机可能在此时具有WiFi访问权限)。

1
以下是有关编程的内容,从英语翻译成中文。仅返回翻译后的文本:http://stackoverflow.com/questions/8211081/android-to-check-if-the-phone-has-a-network-provider/8211179#8211179 - Jan Dragsbaek
1
这并不相同。当移动网络被禁用且 Wi-Fi 已启用(且正常工作)时,((LocationManager)getSystemService(Context.LOCATION_SERVICE)).isProviderEnabled(LocationManager.NETWORK_PROVIDER) 为 true。根据 API:基于基站和 WiFi 接入点的可用性确定位置。 - Cremons
5个回答

19

我终于找到了解决方案。显然,并非所有的手机都有这个选项:

主页 > 菜单 > 设置 > 无线和网络 > 移动网络(复选框)

但是,对于那些有这个选项的手机,这种方法将起作用:

/**
 * @return null if unconfirmed
 */
public Boolean isMobileDataEnabled(){
    Object connectivityService = getSystemService(CONNECTIVITY_SERVICE); 
    ConnectivityManager cm = (ConnectivityManager) connectivityService;

    try {
        Class<?> c = Class.forName(cm.getClass().getName());
        Method m = c.getDeclaredMethod("getMobileDataEnabled");
        m.setAccessible(true);
        return (Boolean)m.invoke(cm);
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

2
不要忘记在AndroidManifest.xml中添加<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>。 - Bao Le
@DanielNugent 有什么想法为什么? - Peter Chaula
@PeterChaula 这是一个安全漏洞,最初根本没有想到这是可能的。Google已经修复了这个安全漏洞,因此现在不可能再这么做了。更多信息请参见此处:https://dev59.com/2F8d5IYBdhLWcg3wsT4b - Daniel Nugent
@DanielNugent 一个必须尽可能避免“hacky”反射的原因。 - Peter Chaula

3

显然,Reflection方法有一个更加简洁的替代方案:

final ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 
final NetworkInfo networkInfo = cm.getActiveNetworkInfo();
int type = networkInfo.getType();
String typeName = networkInfo.getTypeName();
boolean connected = networkInfo.isConnected()

当连接到移动网络时,networkInfo.getType()将返回“0”,当通过WIFI连接时,将返回“1”。networkInfo.getTypeName()将返回字符串“mobile”或“WIFI”。而networkInfo.isConnected()将告诉您是否有活动连接。


@sandeep_jagtap 是的,所有这些功能从 Android API 级别 1 就已经存在了。 - bvanvelsen - ACA Group
如果手机处于飞行模式,即使“移动数据”设置已启用,“getActiveNetworkInfo()”也将返回null。 - Caner

3

针对 Android 5.0+ (API 21+) 的更新

在某些设备上,通过反射调用 getMobileDataEnabled 会导致 Android 5.0+ 上出现 NoSuchMethodException。因此,在接受的答案之外,您可能需要进行第二次检查,以确保未抛出 NoSuchMethodException

...
catch(NoSuchMethodException e)
{
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
  {
      isDataEnabled = Settings.Global.getInt(context.getContentResolver(), "mobile_data", 0) == 1;
  }
}

我在Settings.Global中没有看到任何名为“mobile_data”的常量https://developer.android.com/reference/android/provider/Settings.Global.html。我想知道它是如何工作的,或者你有什么想法。 - LoveForDroid
@LoveForDroid 的 "@Hide" 注解。 - Dogcat
这段代码适用于OS 7+吗?并且你能提供适用于OS < 5的代码吗? - kemdo

1

你可以使用以下代码,适用于所有API版本:

ConnectivityManager cm =
            (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    boolean isConnected = activeNetwork != null &&
                          activeNetwork.isConnectedOrConnecting();

if(isConnected)
{
if(activeNetwork.getType()==ConnectivityManager.TYPE_MOBILE)
return true;    

else
    return false;
}

else
    return false;

这将告诉我有关我的活动网络的信息。我想知道用户是否关闭了移动网络。如果我连接到Wifi,答案仍然可能是肯定或否定。 - Cremons
只获取活动网络,如果用户同时启用了WiFi和3G,则始终返回TYPE_WIFI(如果通过WiFi连接)。 - kemdo

0
    PackageManager pm = context.getPackageManager();
    boolean hasTelephony = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);

1
你能否添加一些关于你的代码到底是做什么的解释? - Math
请参考以下链接以了解有关“PackageManager”的内容:https://developer.android.com/reference/android/content/pm/PackageManager.html - Peter

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