如何判断“移动网络数据”是启用还是禁用(即使通过WiFi连接)?

时间:2012-10-09 19:05:37

标签: android networking network-connection

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

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

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

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

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

无论如何判断移动网络数据是否在没有轮询的情况下启用以查看是否已连接?

修改

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

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

mob_avail返回为'true',但我已禁用移动网络数据,因此我预计它会为'false'

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

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

更新

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

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

WiFi关闭 - 移动数据

WiFi On - 移动数据关闭

WiFi On - 移动数据

并得到以下结果:

  

WiFi关闭:

     

移动[HSUPA],状态:已连接/已连接,原因:未知,额外:   internet,漫游:false,failover:false,isAvailable:true,   featureId:-1,userDefault:false

     

WiFi开启/移动关闭

     

NetworkInfo:type:mobile [HSUPA],状态:DISCONNECTED / DISCONNECTED,   reason:connectionDisabled,extra :( none),漫游:false,   failover:false,isAvailable:true,featureId:-1,userDefault:   假

     

启用WiFi /移动设备

     

NetworkInfo:type:mobile [HSPA],状态:DISCONNECTED / DISCONNECTED,   reason:connectionDisabled,extra :( none),漫游:false,   failover:false,isAvailable:true,featureId:-1,userDefault:   假

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

澄清

想要查看我的手机当前是否通过移动网络连接。我 AM 试图确定用户是否已通过移动网络启用/禁用数据访问。他们可以通过转到设置 - >打开和关闭它无线和网络设置 - >移动网络设置 - >已启用数据

16 个答案:

答案 0 :(得分:109)

以下代码将告诉您“移动数据”是否已启用,无论此时是否有活动数据连接处于活动状态,或者无论是否启用了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才能使用此代码。

答案 1 :(得分:32)

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

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

更新以检查SIM卡是否可用。谢谢你指出murat。

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

答案 2 :(得分:21)

一种方法是检查用户是否在“设置”中激活了移动数据,如果wifi关闭,则很可能会使用该数据。 虽然它在API中使用隐藏值,但它可以使用反射,但它不会使用反射:

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

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

来源: Android API call to determine user setting "Data Enabled"

答案 3 :(得分:4)

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

getDataState()TelephonyManager方法非常有用。

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

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

答案 4 :(得分:2)

你可以尝试这样的事情:

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

我认为使用NetworkInfo class和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;

答案 7 :(得分: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]
               .................
          }
}

}

答案 8 :(得分: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";
    }

答案 9 :(得分: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();

答案 10 :(得分:0)

使用TelephonyManager

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

tm.isDataEnabled()

根据android文档

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

答案 11 :(得分: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;
        }

答案 12 :(得分:0)

有一种解决方法,可以检查数据连接是否打开。但是我不确定它是否可以在所有设备上运行。您需要检查一下。 (它可以在Android一台设备上使用)

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

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

  • 重新启动电话时,此方法还将返回0,因为计算从0字节开始。

答案 13 :(得分: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权限才能使用此代码

答案 14 :(得分:0)

有一个似乎很有效的简单API

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

答案 15 :(得分:0)

<form><input id="custom_photo" type="file" name="properties[Logo]" class="btn" style=" padding: 0px!important;" required /></form> </div> </div> </div> </div> <input data-btn-addToCart type="submit" name="add" class="btn" {% if settings.enable_multilang %}data-translate="products.product.add_to_cart"{%endif%} id="product-add-to-cart" value="{{ 'products.product.add_to_cart' | t }}" data-form-id="#add-to-cart-form"> {% else %} <input type="submit" name="add" class="btn" {% if settings.enable_multilang %}data-translate="products.product.unavailable"{%endif%} id="product-add-to-cart" disabled value="{{ 'products.product.unavailable' | t }}"> {% endif %} {% include 'wishlist-product' %} {% form 'product', product %} {% if section.settings.enable_payment_button and current_variant.available %} {{ form | payment_button }} {% endif %} {% endform %} </div> 起已弃用,Android建议使用ConnectivityManager.allNetworkInfo

getNetworkCapabilities