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

Kev*_*haw 63 networking android network-connection

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

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

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

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

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

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

编辑

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

 boolean mob_avail = 
 conMan.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isAvailable();
Run Code Online (Sandbox Code Playgroud)

mob_avail返回为'true',但我已禁用移动网络数据,所以我希望它是'false'

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

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

UPDATE

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

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

WiFi关闭 - 移动数据

WiFi On - 移动数据关闭

WiFi On - 移动数据

并得到以下结果:

WiFi关闭:

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

WiFi On/Mobile OFF

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

WiFi On/Mobile On

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

因此,您可以看到isAvailable每次都返回true,并且状态仅在WiFi处于影响状态时显示为Disconnected.

澄清

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

Dav*_*ser 115

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

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

  • 这在Android 5.0中不起作用 (9认同)
  • 这有效,但它带来了很大的风险,因为 API 开发人员可以随时删除私有方法 (3认同)
  • 辉煌!绝对完美.非常感谢,它花了我1/3的声誉,但它完全符合我的需要,所以非常好.我可以请你对代码做一点解释吗?它与我一直在尝试的内容以及作为解决方案向我建议的内容不同.我说你使用反射是对的吗?如果那是什么,我对反思有点模糊.它是后门技巧还是Android的真正支持功能?无论如何,再次感谢.你的明星! (2认同)
  • @DavidWasser很棒.但是我需要提出一个问题,如果使用proguard"getMobileDataEnabled"字符串将被转换为其他导致错误结果的东西.Proguard与Reflection不兼容 (2认同)

sNa*_*ash 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @LoveForDroid 它是 Settings.Global 类的隐藏成员。您可以在 aosp 源代码中找到它。 (2认同)
  • 我见过至少一个设备,其中设置中的“禁用移动数据”选项不会更改此设置(但会导致 TelephonyManager.isDataEnabled() 返回 false)。可能是设置中的错误,因为向下滑动菜单中的移动数据图标也没有显示禁用,但它确实禁用了移动数据。 (2认同)

Ale*_*sio 21

一种方法是检查用户是否在设置中激活了移动数据,如果wifi关闭,则最有可能使用该数据.这工作(测试),虽然它在API中使用隐藏值,但它不使用反射:

boolean mobileDataAllowed = Settings.Secure.getInt(getContentResolver(), "mobile_data", 1) == 1;
Run Code Online (Sandbox Code Playgroud)

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

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

  • 测试4.4.4和5.0.1. (3认同)
  • 如果没有SIM卡,则返回true,您还应该添加SIM验证 (3认同)

Moh*_*ohK 6

@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) {
//          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 = tm.getDataState();
            Log.v(TAG,"tm.getDataState() : "+ dataState);
            if(dataState != TelephonyManager.DATA_DISCONNECTED){
                mobileYN = true;
            }

        }

        return mobileYN;
    }
Run Code Online (Sandbox Code Playgroud)


小智 5

由于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
    }
}
Run Code Online (Sandbox Code Playgroud)