如何在 Android 上以编程方式关闭 3G/数据?

Posted

技术标签:

【中文标题】如何在 Android 上以编程方式关闭 3G/数据?【英文标题】:How can i turn off 3G/Data programmatically on Android? 【发布时间】:2012-09-14 03:30:23 【问题描述】:

不是 Wifi,而是 3G/数据。

【问题讨论】:

如果它是重复的,我不会感到惊讶,但不确定为什么会有投票结束这个不是一个真正的问题。 【参考方案1】:

没有官方的方法可以做到这一点。但是,它可以通过反射非官方实现。

对于 android 2.3 及更高版本:

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

这还需要以下权限。

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

适用于 Android 2.2 及以下版本:

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

这需要以下权限:

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

请注意,这两个都是非官方的,可能不再有效。由于 2.2 及以下的方法在 2.3 上发生了故障,因此不需要再证明这种事情会被破坏。

【讨论】:

嘿 Raghav,你能告诉我哪些包导入到 2.3 的项目中吗?当我导入 java.lang.reflect.Method;我遇到了一些错误。 我可以将您的代码用作私有 void setMobileDataEnabled(boolean enabled) Context context ; // ... ?换句话说,你为什么选择使用 Context 作为参数? @gcc 这样的方法通常进入实用程序类,我们需要一个 Context 才能获取 SystemServices 等。但是,如果您将其直接放在 Activity 或 Service 中,则可以删除上下文。 如果我在 Activity 类的顶部写了Context context;。然后,我调用了你的函数。是否按预期运行?或者,我应该初始化或分配上下文吗?无论如何,谢谢 你应该添加 context = getApplicationContext(); 到你的 onCreate() 以便能够使用它。【参考方案2】:

try/catch块包围代码

public void mobiledataenable(boolean enabled) 

try  
        final ConnectivityManager conman = (ConnectivityManager)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);
    
    catch (Exception e)
    
        e.printStackTrace();
         

在 Manifest 中,添加以下权限:

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

【讨论】:

【参考方案3】:
 public void onClick(View view)
        ConnectivityManager dataManager;
        dataManager  = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        Method dataMtd = null;
        try 
            dataMtd = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", boolean.class);
         catch (NoSuchMethodException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
        dataMtd.setAccessible(true);
        try 
            dataMtd.invoke(dataManager, true);
         catch (IllegalArgumentException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
         catch (IllegalAccessException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
         catch (InvocationTargetException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
           
    

【讨论】:

+1,它确实在 Android 4.3 上打开了移动数据;但我们需要添加上一个答案建议的权限 这种方法不再适用于 Android 4.2.2 及更高版本,因为 android.permission.MODIFY_PHONE_STATE 现在是一个受保护的权限,它只被授予到系统应用程序。【参考方案4】:

我还在使用 2.1,所以这个解决方案适合我。

但您还需要包含 MODIFY_PHONE_STATE 权限。

完整代码(带有工具按钮)2.1:

package com.rivaldo.turn3gonoff;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.telephony.TelephonyManager;
import android.view.Menu;
import android.widget.CompoundButton;
import android.widget.ToggleButton;

public class Turn3GOnOff extends Activity 

Method dataConnSwitchmethod_ON;
Method dataConnSwitchmethod_OFF;
Class telephonyManagerClass;
Object ITelephonyStub;
Class ITelephonyClass;


@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_turn3_gon_off);

    GetDataConnectionAPI();

    ToggleButton toggle = (ToggleButton) findViewById(R.id.toggleButton);
    toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() 
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 
            if (isChecked) 
                turn3GOn();
             else 
                turn3GOff();
            
        
    );



private void GetDataConnectionAPI() 
    this.getApplicationContext();
    TelephonyManager telephonyManager = 
                    (TelephonyManager) this.getApplicationContext().
                                              getSystemService(Context.TELEPHONY_SERVICE);

    try 
        telephonyManagerClass = Class.forName(telephonyManager.getClass().getName());
        Method getITelephonyMethod = telephonyManagerClass.getDeclaredMethod("getITelephony");
        getITelephonyMethod.setAccessible(true);
        ITelephonyStub = getITelephonyMethod.invoke(telephonyManager);
        ITelephonyClass = Class.forName(ITelephonyStub.getClass().getName());

        dataConnSwitchmethod_OFF = 
                        ITelephonyClass.getDeclaredMethod("disableDataConnectivity");
        dataConnSwitchmethod_ON = ITelephonyClass.getDeclaredMethod("enableDataConnectivity");   
     catch (Exception e)  // ugly but works for me
        e.printStackTrace();
    

private void turn3GOn() 
    dataConnSwitchmethod_ON.setAccessible(true);
    try 
        dataConnSwitchmethod_ON.invoke(ITelephonyStub);
     catch (IllegalArgumentException e) 
        e.printStackTrace();
     catch (IllegalAccessException e) 
        e.printStackTrace();
     catch (InvocationTargetException e) 
        e.printStackTrace();
    


private void turn3GOff() 
    dataConnSwitchmethod_OFF.setAccessible(true);
    try 
        dataConnSwitchmethod_OFF.invoke(ITelephonyStub);
     catch (IllegalArgumentException e) 
        e.printStackTrace();
     catch (IllegalAccessException e) 
        e.printStackTrace();
     catch (InvocationTargetException e) 
        e.printStackTrace();
    



Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.rivaldo.turn3gonoff"
android:versionCode="1"
android:versionName="1.0" >

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-sdk
    android:minSdkVersion="7"
    android:targetSdkVersion="7" />
<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.rivaldo.turn3gonoff.Turn3GOnOff"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>


</application>
</manifest>

activity_turn3_gon_off.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
tools:context=".Turn3GOnOff" >

<ToggleButton
    android:id="@+id/toggleButton"
    android:layout_
    android:layout_
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true"
    android:layout_marginTop="60dp"
    android:textOn="3G on"
    android:textOff="3G off"
    android:text="ToggleButton" />

</RelativeLayout>

【讨论】:

以上是关于如何在 Android 上以编程方式关闭 3G/数据?的主要内容,如果未能解决你的问题,请参考以下文章

在android上以编程方式打开/关闭大写锁定和shift键

在 Android 上以编程方式关闭应用程序的通知

如何在Android上以编程方式启用或禁用GPS?

如何在Android 6.x上以编程方式启用或禁用GPS?

如何在Tomcat上以编程方式自行关闭Spring应用程序

如何在 Android 上以编程方式截取屏幕截图? [复制]