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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12806709/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 12:07:46  来源:igfitidea点击:

How to tell if 'Mobile Network Data' is enabled or disabled (even when connected by WiFi)?

androidnetworkingnetwork-connection

提问by Kevin Bradshaw

I have an app that I want to be able to use to get a connection status report from a remote query.

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

I want to know if WiFi is connected, and if data access is enabled over mobile network.

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

If the WiFi goes out of range I want to know if I can rely on the mobile network.

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

The problem is that data enabled is always returned as true when I am connected by WiFi, and I can only properly query the mobile network when not connected by WiFi.

问题是当我通过WiFi连接时,数据启用始终返回为true,并且我只能在未通过WiFi连接时正确查询移动网络。

all the answers I have seen suggest polling to see what the current connection is, but I want to know if mobile network is available should I need it, even though I might be connected by WiFi at present.

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

Is there anyway of telling whether mobile network data is enabled without polling to see if is connected?

有没有办法知道是否启用了移动网络数据而无需轮询以查看是否已连接?

EDIT

编辑

So when connected by WiFi If I go to settings and deselect 'Data Enabled' and then in my app I do this:

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

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

mob_avail is returned as 'true', but I have disabled Mobile Network Data, so I would expect it to be 'false'

mob_avail 返回为“true”,但我已禁用移动网络数据,因此我希望它为“false”

If I turn off the WiFi, there is (rightly) no connection as I have disabled mobile network data.

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

so how do I check if mobile network data is enabled when I am connected by WiFi?

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

UPDATE

更新

I took a look at getAllNetworkInfo() as suggested in the comments by ss1271

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

I outputted the info returned about the mobile network under the following 3 conditions

我在以下3种情况下输出了有关移动网络的返回信息

WiFi Off - Mobile Data on

WiFi 关闭 - 移动数据开启

WiFi On - Mobile Data off

WiFi 开 - 移动数据关

WiFi On - Mobile Data on

WiFi 开启 - 移动数据开启

and got the following results:

并得到以下结果:

With WiFi OFF:

mobile[HSUPA], state: CONNECTED/CONNECTED, reason: unknown, extra: internet, roaming: false, failover: false, isAvailable: true, featureId: -1, userDefault: false

With WiFi On / Mobile OFF

NetworkInfo: type: mobile[HSUPA], state: DISCONNECTED/DISCONNECTED, reason: connectionDisabled, extra: (none), roaming: false, failover: false, isAvailable: true, featureId: -1, userDefault: false

With WiFi On / Mobile On

NetworkInfo: type: mobile[HSPA], state: DISCONNECTED/DISCONNECTED, reason: connectionDisabled, extra: (none), roaming: false, failover: false, isAvailable: true, featureId: -1, userDefault: false

关闭 WiFi:

移动[HSUPA],状态:CONNECTED/CONNECTED,原因:未知,额外:互联网,漫游:假,故障转移:假,isAvailable:真,功能ID:-1,用户默认:假

开启 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

So as you can see isAvailable returned true each time, and state only showed as Disconnected when WiFi was in affect.

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

CLARIFICATION

澄清

I am NOTlooking to see if my phone is currently connected by Mobile Network. I AMtrying to establish whether or not the user has enabled / disabled Data access over mobile network. They can turn this on and off by going to Settings -> Wireless and Network Settings ->Mobile Network Settings -> Data enabled

看,看看我的手机是目前移动网络连接。我AM试图建立在移动网络中的用户是否已启用/禁用数据访问。他们可以通过转到设置 -> 无线和网络设置 -> 移动网络设置 -> 启用数据来打开和关闭此功能

回答by David Wasser

The following code will tell you if "mobile data" is enabled or not, regardless of whether or not there is a mobile data connection active at the moment or whether or not wifi is enabled/active or not.This code only works on Android 2.3 (Gingerbread) and later. Actually this code also works on earlier versions of Android as well ;-)

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

Note: you will need to have permission android.permission.ACCESS_NETWORK_STATEto be able to use this code.

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

回答by sNash

I've upgraded Allesio's answer. Settings.Secure's mobile_data int has moved to Settings.Global since 4.2.2.

Try This code when you want to know if mobile network is enabled even when wifi is enabled and connected.

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

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

Updated to check if SIM Card is available. Thanks for pointing out murat.

更新以检查 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;
    }
}

回答by Alessio

One way is to check whether the user has mobile data activated in the Settings, which most likely will be used if wifi goes off. This works (tested), and it doesn't use reflection, although it uses an hidden value in the API:

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

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

Depending on the API, you need to check Settings.Global instead of Settings.Secure, as pointed out by @user1444325.

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

Source: Android API call to determine user setting "Data Enabled"

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

回答by MohK

@sNash's function works great. But in few devices I found it returns true even if data is disabled. So I found one alternate solution which is in Android API.

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

getDataState()method of TelephonyManagerwill be very useful.

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

I updated @snash's function with the above function used. Below function returns false when cellular data is disabled otherwise true.

我使用上述函数更新了@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;
    }

回答by Milo?

You can try something like that:

你可以尝试这样的事情:

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
}

If you are interested if you are realy connected, use

如果你有兴趣,如果你真的连接,使用

NetworkInfo.State.CONNECTED 

only, instead of

只是,而不是

NetworkInfo.State.CONNECTED || NetworkInfo.State.CONNECTING

回答by SubqueryCrunch

Here is a xamarin solution to this problem:

这是针对此问题的 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: Make sure you have all the permissions for this code.

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

回答by Ralph Chen

use TelephonyManager

使用电话管理器

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

tm.isDataEnabled()

According to android documentation

根据android文档

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

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

回答by Brian Hong

Here is a simple solution from two other answers:

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

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

回答by Thamidu de Harshitha

Well there is a workaround to check if the data connection is on. But I am not sure whether it will work on every device. You need to check that. (It worked on Android one device)

那么有一个解决方法来检查数据连接是否打开。但我不确定它是否适用于所有设备。你需要检查一下。(它适用于 Android 一台设备)

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

If you are not aware about this method, it returns the total of bytes recieved through mobile network since the device boot up. When you turn off the mobile data connection, it will return Zero (0). When you turn on, it will return the total of bytes again. But you need to aware that there is a problem which can happen when using this workaround.

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

  • This method will also return 0 when you reboot the phone because the calculation starts from 0 bytes.
  • 当您重新启动手机时,此方法也会返回 0,因为计算从 0 字节开始。

回答by Annas Bin Waheed

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

Note: you will need to have permission android.permission.ACCESS_NETWORK_STATE to be able to use this code

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