【问题标题】:How to disable Mobile Data on Android如何在 Android 上禁用移动数据
【发布时间】:2010-09-04 21:57:26
【问题描述】:

在有人告诉我购买应用程序之前快速回顾一下。 =)

我刚买了一个 EVO,它很快就耗尽了电池。我下载了 JuiceDefender 来管理我的移动数据连接。这似乎效果很好。但是,这些设置非常有限(即使在付费版本上也是如此)。

截至目前,我正在尝试开发一个更可定制的节电应用程序。我首先要做的主要事情是能够随意启用/禁用移动数据连接。

问题是我找不到任何代码 sn-ps 或有关如何执行此操作的文章。我唯一发现的是以下内容。我不知道这有多准确,但这是我在浏览 developer.android.com 时所能拼凑出来的全部内容

ConnectivityManager cm = (ConnectivityManager) this.getSystemService(CONNECTIVITY_SERVICE);
cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "android.net.conn.CONNECTIVITY_CHANGE");

State state = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();
textView.setText(state.name());

如果有人能指出任何可以提供帮助的东西,将不胜感激。

更新

Sprint 上的 HTC Evo 似乎不使用 APN 设置。我通过下载 APNDroid 并观察它不起作用对此进行了测试。然后我制作了一个快速应用程序将所有 APN 条目转储到屏幕上。这产生了一个结果,它是针对 mms 的。

查看 JuiceDefender 运行时的手机信息,我发现 GSRP 网络正在打开和关闭。这让我相信可以通过代码来做到这一点,即使我发现询问同一问题的每个页面都表示无法完成。关键是他们都说要像 APNDroid 那样做。请有人给我一些见解。

谢谢!

【问题讨论】:

    标签: android


    【解决方案1】:

    从“Gingerbread”开始,您可以使用 IConnectivityManager.setMobileDataEnabled() 方法。 它隐藏在 API 中,但可以通过 reflection 访问。 http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/net/ConnectivityManager.java#376

    使用此方法,您可以更改系统设置: '设置 -> 无线和网络 -> 移动网络设置 -> 数据启用'

    代码示例:

    private void setMobileDataEnabled(Context context, boolean enabled) {
        final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        final Class conmanClass = Class.forName(conman.getClass().getName());
        final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
        iConnectivityManagerField.setAccessible(true);
        final Object iConnectivityManager = iConnectivityManagerField.get(conman);
        final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
        final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
        setMobileDataEnabledMethod.setAccessible(true);
    
        setMobileDataEnabledMethod.invoke(iConnectivityManager, enabled);
    }
    

    您还需要 CHANGE_NETWORK_STATE 权限。

    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
    

    不用说,这种方法在未来的 android 版本中可能不起作用。但我猜想“3G watchdog”、“APNdroid”或“DataLock”等应用程序都是这样工作的。


    更新
    Lollipop 上不再提供 setMobileDataEnabled 方法

    【讨论】:

    • 在我的真实手机中,当 WiFi 开启时,3G 不会保持开启状态。它短暂闪烁然后又熄灭。怎么保持?
    • InvocationTargetException in 2.2.1
    • 注意此方法自 Android 4.3 起已弃用。这将不再起作用。
    • 那么对于OS 4.3版本应该使用哪种方法打开移动数据?
    • 在私有 mService 字段上调用 ​​setMobileDataEnabled 而不直接使用 ConnectivityManager 是否有原因?即pastebin.com/tjNin7yR ?
    【解决方案2】:

    数据连接禁用和启用 APIS 隐藏在 SDK 中,不会暴露给用户,这可以通过使用 java 反射技术访问 ITelephony 接口来实现。

    给你:

        Method dataConnSwitchmethod;
        Class telephonyManagerClass;
        Object ITelephonyStub;
        Class ITelephonyClass;
    
        TelephonyManager telephonyManager = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
    
        if(telephonyManager.getDataState() == TelephonyManager.DATA_CONNECTED){
            isEnabled = true;
        }else{
            isEnabled = false;  
        }   
    
        telephonyManagerClass = Class.forName(telephonyManager.getClass().getName());
        Method getITelephonyMethod = telephonyManagerClass.getDeclaredMethod("getITelephony");
        getITelephonyMethod.setAccessible(true);
        ITelephonyStub = getITelephonyMethod.invoke(telephonyManager);
        ITelephonyClass = Class.forName(ITelephonyStub.getClass().getName());
    
        if (isEnabled) {
            dataConnSwitchmethod = ITelephonyClass
                    .getDeclaredMethod("disableDataConnectivity");
        } else {
            dataConnSwitchmethod = ITelephonyClass
                    .getDeclaredMethod("enableDataConnectivity");   
        }
        dataConnSwitchmethod.setAccessible(true);
        dataConnSwitchmethod.invoke(ITelephonyStub);
    

    【讨论】:

    • 这不适用于 Gingerbread 2.3+:stackoverflow.com/questions/4715250/…
    • 来自 phaniKumar 的上述解决方案还需要在 AndroidManifest.xml 中声明的 &lt;uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/&gt;。未经许可,您将收到InvocationTargetException 错误。
    • 我尝试了上面的代码..它给了我 java.lang.SecurityException: 用户 10126 和当前进程都没有 android.permission.MODIFY_PHONE_STATE...当我包含 。我收到“权限仅授予系统应用程序”..错误..我没有其他方法可以访问此功能。 ?
    【解决方案3】:

    自 Gingerbread 以来,通过更改 APN 名称来切换移动数据网络连接不再有效。 虽然反射代码可能是解决问题的正确方法,但它不会起作用,因为应用程序需要 Alex P 解释的 android.permission.MODIFY_PHONE_STATE 权限。否则你会得到这个讨厌的异常:

    03-18 21:54:55.074: WARN/System.err(1851): java.lang.reflect.InvocationTargetException
    (...)
    03-18 21:54:55.263: WARN/System.err(1851): Caused by: java.lang.SecurityException: Neither user 10037 nor current process has android.permission.MODIFY_PHONE_STATE.
    (...)
    03-18 21:54:55.303: WARN/System.err(1851):     at com.android.internal.telephony.ITelephony$Stub$Proxy.disableDataConnectivity(ITelephony.java:888)
    

    很遗憾,您无法设置此权限,因为这是应用程序不允许的 3 级权限:

    03-18 21:48:39.334: WARN/PackageManager(75): Not granting permission android.permission.MODIFY_PHONE_STATE to package XXX (protectionLevel=3 flags=0x8be46)
    

    我认为除了使用自己的固件之外,没有人有办法覆盖权限授予抑制。

    【讨论】:

      【解决方案4】:

      我认为 Android 设备上有两种主要的移动数据连接类型:WiFi 和 3G/HSDPA/等。

      而且,您应该能够以编程方式禁用 WiFi,但我认为只能通过更改 APN 的名称来禁用 3G/HSDPA/etc 连接。我之所以这么说是因为流行的应用程序APNDroid 就是这样做的。

      【讨论】:

      • 非常感谢。查看似乎正在发生的事情的 APNDroid 代码。我确信我可以稍微翻转一下。哦,好吧,嘿嘿。
      • 爆炸!下载了这个应用,好像在Evo 4G上不行。
      【解决方案5】:

      请注意,Android 2.3 及更高版本不再支持“android.permission.MODIFY_PHONE_STATE”。

      why 2.3 version of android does not hava android.permission.MODIFY_PHONE_STATE ? and what is the solution for this?

      【讨论】:

        【解决方案6】:

        要添加切换按钮,您可以使用此代码以及弗拉基米尔的回答:

        TelephonyManager telephonyManager = (TelephonyManager) context
                        .getSystemService(Context.TELEPHONY_SERVICE);
        switch (telephonyManager.getDataState()) {
                case TelephonyManager.DATA_CONNECTED:
                    setMobileDataEnabledMethod.invoke(iConnectivityManager, false);
                    break;
                case TelephonyManager.DATA_DISCONNECTED:
                    setMobileDataEnabledMethod.invoke(iConnectivityManager, true);
                    break;
                }
        

        这种反射解决方法在 android 4.0.4 上仍然适用于我

        【讨论】:

          【解决方案7】:

          @Mariux:你可能忘记在 AndroidManifest.xml 中添加&lt;uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /&gt;

          【讨论】:

          • 嘿,我尝试了所有数据连接权限,但这在 Android 4.0.4 平板电脑中不起作用..
          【解决方案8】:
              final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
              final Class conmanClass = Class.forName(conman.getClass().getName());
              final Field connectivityManagerField = conmanClass.getDeclaredField("mService");
              connectivityManagerField.setAccessible(true);
              final Object connectivityManager = connectivityManagerField.get(conman);
              final Class connectivityManagerClass = Class.forName(connectivityManager.getClass().getName());
              final Method setMobileDataEnabledMethod = connectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
              setMobileDataEnabledMethod.setAccessible(true);
          
              setMobileDataEnabledMethod.invoke(connectivityManager, enabled); // pass true or false
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-10-10
            • 2013-05-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多