72

我有一个应用程序,我希望能够使用它从远程查询中获取连接状态报告。

我想知道是否连接了 WiFi,以及是否通过移动网络启用了数据访问。

如果 WiFi 超出范围,我想知道我是否可以依赖移动网络。

问题是我通过WiFi连接时,数据启用总是返回true,而我只有在没有WiFi连接时才能正确查询移动网络。

我看到的所有答案都建议轮询以查看当前连接是什么,但我想知道移动网络是否可用,如果我需要它,即使我目前可能通过 WiFi 连接。

无论如何都可以告诉是否启用了移动网络数据而无需轮询以查看是否已连接?

编辑

因此,当通过 WiFi 连接时,如果我转到设置并取消选择“启用数据”,然后在我的应用程序中执行以下操作:

 boolean mob_avail = 
 conMan.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isAvailable();

mob_avail 返回为“真”,但我已禁用移动网络数据,所以我希望它为“假”

如果我关闭 WiFi,则(正确地)没有连接,因为我禁用了移动网络数据。

那么,当我通过 WiFi 连接时,如何检查是否启用了移动网络数据?

更新

我按照 ss1271 的评论中的建议查看了 getAllNetworkInfo()

我在以下 3 个条件下输出了返回的有关移动网络的信息

WiFi 关闭 - 移动数据开启

WiFi 开启 - 移动数据关闭

WiFi 开启 - 移动数据开启

并得到以下结果:

关闭 WiFi 时:

移动[HSUPA],状态:CONNECTED/CONNECTED,原因:未知,额外:互联网,漫游:false,故障转移:false,isAvailable:true,featureId:-1,userDefault:false

WiFi开启/移动关闭

NetworkInfo:类型:mobile[HSUPA],状态:DISCONNECTED/DISCONNECTED,原因:connectionDisabled,额外:(无),漫游:false,故障转移:false,isAvailable:true,featureId:-1,userDefault:false

WiFi开启/移动开启

NetworkInfo:类型:mobile[HSPA],状态:DISCONNECTED/DISCONNECTED,原因:connectionDisabled,额外:(无),漫游:false,故障转移:false,isAvailable:true,featureId:-1,userDefault:false

因此,您可以看到 isAvailable 每次都返回 true,并且状态仅在 WiFi 生效时显示为已断开连接。

澄清

不想查看我的手机当前是否通过移动网络连接。我正在尝试确定用户是否启用/禁用了移动网络上的数据访问。他们可以通过转到设置 -> 无线和网络设置 -> 移动网络设置 -> 启用数据来打开和关闭此功能

4

17 回答 17

129

以下代码将告诉您是否启用了“移动数据”,无论此时是否有移动数据连接处于活动状态或 wifi 是否启用/处于活动状态。此代码仅适用于 Android 2.3 (Gingerbread) 及更高版本。实际上,此代码也适用于早期版本的 Android ;-)

    boolean mobileDataEnabled = false; // Assume disabled
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    try {
        Class cmClass = Class.forName(cm.getClass().getName());
        Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
        method.setAccessible(true); // Make the method callable
        // get the setting for "mobile data"
        mobileDataEnabled = (Boolean)method.invoke(cm);
    } catch (Exception e) {
        // Some problem accessible private API
        // TODO do whatever error handling you want here
    }

注意:您需要获得android.permission.ACCESS_NETWORK_STATE使用此代码的权限。

于 2012-10-12T18:19:35.323 回答
37

我已经升级了 Allesio 的答案。Settings.Secure 的 mobile_data int 自 4.2.2 起已移至 Settings.Global。

如果您想知道移动网络是否已启用,即使已启用并连接了 wifi,请尝试使用此代码。

更新以检查 SIM 卡是否可用。感谢您指出穆拉特。

boolean mobileYN = false;

TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) {
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1)
    {
        mobileYN = Settings.Global.getInt(context.getContentResolver(), "mobile_data", 1) == 1;
    }
    else{
        mobileYN = Settings.Secure.getInt(context.getContentResolver(), "mobile_data", 1) == 1;
    }
}
于 2015-08-27T02:35:02.783 回答
22

一种方法是检查用户是否在“设置”中激活了移动数据,如果 wifi 关闭,很可能会使用该数据。这有效(经过测试),它不使用反射,尽管它使用 API 中的隐藏值:

boolean mobileDataAllowed = Settings.Secure.getInt(getContentResolver(), "mobile_data", 1) == 1;

正如@user1444325 所指出的,根据 API,您需要检查 Settings.Global 而不是 Settings.Secure。

来源: Android API 调用以确定用户设置“数据已启用”

于 2015-04-14T10:57:08.470 回答
4

@sNash 的功能很好用。但在少数设备中,即使数据被禁用,我发现它也会返回 true。所以我在 Android API 中找到了一种替代解决方案。

TelephonyManager的getDataState()方法将非常有用。

我用上面使用的函数更新了@snash 的函数。当蜂窝数据被禁用时,下面的函数返回 false,否则返回 true。

private boolean checkMobileDataIsEnabled(Context context){
        boolean mobileYN = false;

        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (tm.getSimState() == TelephonyManager.SIM_STATE_READY) {
            TelephonyManager tel = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
//          if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1)
//          {
//              mobileYN = Settings.Global.getInt(context.getContentResolver(), "mobile_data", 0) == 1;
//          }
//          else{
//              mobileYN = Settings.Secure.getInt(context.getContentResolver(), "mobile_data", 0) == 1;
//          }
            int dataState = tel.getDataState();
            Log.v(TAG,"tel.getDataState() : "+ dataState);
            if(dataState != TelephonyManager.DATA_DISCONNECTED){
                mobileYN = true;
            }

        }

        return mobileYN;
    }
于 2017-10-11T04:48:06.670 回答
3

你可以尝试这样的事情:

ConnectivityManager conMan = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

//mobile
State mobile = conMan.getNetworkInfo(0).getState();

//wifi
State wifi = conMan.getNetworkInfo(1).getState();


if (mobile == NetworkInfo.State.CONNECTED || mobile == NetworkInfo.State.CONNECTING) 
{
    //mobile
}
else if (wifi == NetworkInfo.State.CONNECTED || wifi == NetworkInfo.State.CONNECTING) 
{
    //wifi
}

如果您对真正的连接感兴趣,请使用

NetworkInfo.State.CONNECTED 

只是,而不是

NetworkInfo.State.CONNECTED || NetworkInfo.State.CONNECTING
于 2012-10-12T15:42:46.987 回答
3

由于ConnectivityManager.allNetworkInfo已弃用,Android 建议使用getNetworkCapabilities

fun isOnMobileData(): Boolean {
    val connectivityManager =
        context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
    val all = connectivityManager.allNetworks

    return all.any {
        val capabilities = connectivityManager.getNetworkCapabilities(it)
        capabilities?.hasTransport(TRANSPORT_CELLULAR) == true
    }
}
于 2020-01-15T03:23:25.637 回答
2

使用 TelephonyManager

TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

tm.isDataEnabled()

根据android文档

https://developer.android.com/reference/android/telephony/TelephonyManager.html#isDataEnabled()

于 2018-12-20T04:39:35.213 回答
1

我认为使用NetworkInfo 类和 isConnected 应该可以工作:

ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);

return info != NULL || info.isConnected();

并检查移动数据是否已连接。在我测试之前我不能确定。直到明天我才能做到这一点。

TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

if(tm .getDataState() == tm .DATA_CONNECTED)
   return true;
于 2012-10-12T15:49:27.547 回答
1

这是针对此问题的 xamarin 解决方案:

    public static bool IsMobileDataEnabled()
    {
        bool result = false;

        try
        {
            Context context = //get your context here or pass it as a param

            if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr1)
            {
                //Settings comes from the namespace Android.Provider
                result = Settings.Global.GetInt(context.ContentResolver, "mobile_data", 1) == 1;
            }
            else
            {
                result = Settings.Secure.GetInt(context.ContentResolver, "mobile_data", 1) == 1;
            }
        }
        catch (Exception ex)
        {
            //handle exception
        }

        return result;
    }

PS:确保您拥有此代码的所有权限。

于 2016-08-16T10:19:52.387 回答
0

您必须使用 ConnectivityManager,并且可以在此处找到 NetworkInfo 详细信息

于 2012-10-09T19:22:13.583 回答
0
To identify which SIM or slot is making data connection active in mobile, we need to register action android:name="android.net.conn.CONNECTIVITY_CHANGE"  with permission   
uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" &    uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"

    public void onReceive(Context context, Intent intent) 
 if (android.net.conn.CONNECTIVITY_CHANGE.equalsIgnoreCase(intent
                .getAction())) {

IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
 IConnectivityManager service =  IConnectivityManager.Stub.asInterface(b);
NetworkState[] states = service.getAllNetworkState();

 for (NetworkState state : states) {

                if (state.networkInfo.getType() == ConnectivityManager.TYPE_MOBILE
                        && state.networkInfo.isConnected()) {

 TelephonyManager mTelephonyManager = (TelephonyManager) context
                        .getSystemService(Context.TELEPHONY_SERVICE);
         int slotList =  { 0, 1 };
          int[] subId = SubscriptionManager.getSubId(slotList[0]);
          if(mTelephonyManager.getDataEnabled(subId[0])) {
             // this means data connection is active for SIM1 similary you 
             //can chekc for SIM2 by slotList[1]
               .................
          }
}

}
于 2015-06-15T12:41:34.147 回答
0
    ConnectivityManager cm = (ConnectivityManager) activity
                        .getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo info = cm.getActiveNetworkInfo();
                String networkType = "";
    if (info.getType() == ConnectivityManager.TYPE_WIFI) {
                    networkType = "WIFI";
                } 
else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {

                    networkType = "mobile";
    }
于 2016-01-04T06:46:58.157 回答
0

根据android文档https://developer.android.com/training/monitoring-device-state/connectivity-monitoring#java

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

NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
                      activeNetwork.isConnectedOrConnecting();
于 2018-07-19T09:16:50.097 回答
0

这是其他两个答案的简单解决方案:

        TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            return tm.isDataEnabled();

        } else {
            return tm.getSimState() == TelephonyManager.SIM_STATE_READY && tm.getDataState() != TelephonyManager.DATA_DISCONNECTED;
        }
于 2019-02-22T01:45:50.990 回答
0

好吧,有一种解决方法可以检查数据连接是否打开。但我不确定它是否适用于所有设备。你需要检查一下。(它适用于 Android 一台设备)

long data = TrafficStats.getMobileRxBytes();
if(data > 0){
    //Data is On
}
else{
    //Data is Off
}

如果您不了解此方法,它会返回自设备启动以来通过移动网络接收的总字节数。当您关闭移动数据连接时,它将返回零 (0)。当您打开时,它将再次返回总字节数。但是您需要注意,使用此解决方法时可能会出现问题。

  • 当您重启手机时,此方法也会返回 0,因为计算是从 0 字节开始的。
于 2019-07-23T15:27:41.880 回答
0
private boolean haveMobileNetworkConnection() {
        boolean haveConnectedMobile = false;

        ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();

        for (NetworkInfo ni : netInfo) {

            if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
                if (ni.isConnected())
                    haveConnectedMobile = true;
        }
        return haveConnectedMobile;
    }

注意:您需要拥有 android.permission.ACCESS_NETWORK_STATE 权限才能使用此代码

于 2019-09-03T08:23:43.533 回答
0

有一个简单的 API 似乎可以正常工作

TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
return tm.isDataEnabled();

于 2019-09-12T08:46:34.037 回答