How can i turn off 3G/Data programmatically on Android?
Asked Answered
M

4

37

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

Not Wifi, but 3G/Data.

Momentous answered 21/9, 2012 at 17:13 Comment(1)
Wouldn't be surprised if it was a duplicate, but not sure why there are votes to close this as not a real question.Raddled
R
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.

Rights answered 21/9, 2012 at 17:24 Comment(14)
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.Shroud
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 ?Selfexistent
@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.Rights
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 , thanksSelfexistent
You should then add context = getApplicationContext(); to your onCreate() to be able to use this.Rights
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 ) * 1000Selfexistent
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 wellRights
The last question ; can I catch same effect with Android Linux or Adb commands ?Selfexistent
It may be possible if you're rooted, but I don't know about any such commands.Rights
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?" @RaghavSoodJackpot
Surround with Try/Catch for safety!Zoroastrianism
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()Zoroastrianism
java.lang.SecurityException: Permission denial: writing to secure settings requires android.permission.WRITE_SECURE_SETTINGSZoroastrianism
So this method will no more work because android.permission.WRITE_SECURE_SETTINGS can only be granted to System apps.Zoroastrianism
A
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"/>
Archiepiscopal answered 28/7, 2014 at 7:47 Comment(0)
P
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();
        }   
    }
Periodical answered 5/12, 2013 at 10:21 Comment(2)
+1, it does turn on mobile data on Android 4.3; but we need to add the permission suggested by the previous answer <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />Kirimia
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.Bolometer
A
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>
Aikens answered 22/3, 2013 at 21:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.