37

How can I turn off 3G/Data programmatically on Android?

Not Wifi, but 3G/Data.

kaiz.net
  • 1,984
  • 3
  • 23
  • 31
chuyitox
  • 543
  • 1
  • 5
  • 12
  • 4
    Wouldn't be surprised if it was a duplicate, but not sure why there are votes to close this as not a real question. – John Carter Sep 22 '12 at 00:43

4 Answers4

53

There is no official way to do this. However, it can be achieved unofficially with reflection.

For Android 2.3 and above:

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

This also requires the following permission.

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

For Android 2.2 and below:

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

This required the following permission:

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

Note that both of these are unofficial and may no longer work. No more proof of this kind of thing breaking should be needed, as the 2.2 and below method broke on 2.3.

Raghav Sood
  • 81,899
  • 22
  • 187
  • 195
  • Hey Raghav, do you tell me which packages imported into project for 2.3 ? When I import java.lang.reflect.Method; I get some error. – Melih Mucuk Oct 04 '12 at 08:36
  • Can I use your code as private void setMobileDataEnabled(boolean enabled) { Context context ; // ... } ? In other words, why are do you choose to use Context as argument ? –  Jan 22 '13 at 06:54
  • @gcc Methods like this usually go into utility classes, and we need a Context to be able to get SystemServices etc. However, if you're putting it directly in an Activity or Service, you can remove the context. – Raghav Sood Jan 22 '13 at 07:14
  • If I wrote `Context context;`at top of the Activity class. Then, I have call your function. Is it run as expected ? OR, should I initialize or assign context to something ? Anyway , thanks –  Jan 22 '13 at 07:37
  • You should then add `context = getApplicationContext();` to your onCreate() to be able to use this. – Raghav Sood Jan 22 '13 at 07:39
  • Can I use same code for 2G or 4G ? Are there any differences ? I think your code is more generel, and it seems it can be applied to them also, if device has ability. Again, ( thank you ) * 1000 –  Jan 22 '13 at 07:44
  • This code just enabled mobile data or disables it. It doesn't specify which technology to use. The device should use whatever is available or specified elsewhere in the settings. So yeah, it should work for 4G as well – Raghav Sood Jan 22 '13 at 07:54
  • The last question ; can I catch same effect with Android Linux or Adb commands ? –  Jan 22 '13 at 07:59
  • It may be possible if you're rooted, but I don't know about any such commands. – Raghav Sood Jan 22 '13 at 08:03
  • Thank You. It's really work. But my question is "When data packet on then it's not show in "Data Usege > Mobile data > ON". why?" @RaghavSood – Jigar Shekh Aug 23 '14 at 11:56
  • Surround with Try/Catch for safety! – Muhammad Babar Sep 25 '14 at 12:48
  • `java.lang.SecurityException: Permission Denial: writing com.android.providers.settings.SettingsProvider uri content://settings/system from pid=6683, uid=10109 requires android.permission.WRITE_SETTINGS, or grantUriPermission()` – Muhammad Babar Sep 26 '14 at 06:56
  • `java.lang.SecurityException: Permission denial: writing to secure settings requires android.permission.WRITE_SECURE_SETTINGS` – Muhammad Babar Sep 26 '14 at 06:58
  • So this method will no more work because `android.permission.WRITE_SECURE_SETTINGS` can only be granted to System apps. – Muhammad Babar Sep 26 '14 at 06:59
5

Surround the code with try/catch blocks

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

In the Manifest, add the following permission:

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
Kristy Welsh
  • 7,828
  • 12
  • 64
  • 106
Swetha
  • 746
  • 10
  • 19
4
 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();
        }   
    }
Lalit Poptani
  • 67,150
  • 23
  • 161
  • 242
  • +1, it does turn on mobile data on Android 4.3; but we need to add the permission suggested by the previous answer – Alberici Sep 17 '15 at 23:43
  • This approach no longer works for Android Version 4.2.2 and higher because **android.permission.MODIFY_PHONE_STATE** is now a **Protected Permission** which is only granted to System Apps. – SilSur Mar 11 '18 at 10:45
2

I'm still on 2.1, so this solution works for me.

But you need also to include MODIFY_PHONE_STATE permision.

Full code (with a toogle button) 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_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".Turn3GOnOff" >

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

</RelativeLayout>
Ricardo Rivaldo
  • 1,687
  • 2
  • 15
  • 13