12

I am writing a little app that only I will use and I want to pragmatically enable / disable my mobile data on a rooted android 4.5 device (I am running a custom Android L for Nexus 4).

I have looked for a while and I found the methods with reflection that worked until android 4.3. I have also seen the method from this post Toggle mobile data programmatically on Android 4.4.2 but this requires cyanogenmod.

From what I can find on the internet this is impossible for non-root apps but my question is:

is there something I can do with my root privileges to accomplish this?

Community
  • 1
  • 1
Nactive
  • 540
  • 1
  • 7
  • 17
  • I am looking for the same thing. Please update your answer if you find a solution. setMobileDataEnabled is still present in Android L if you go through the methods in ConnectivityManager source code, but when you look for it via reflection, it seems to be gone. I am also OK with using root privileges to achieve this, but don't know how. – Flyview Sep 25 '14 at 16:20
  • in Android L if you push device_owner.xml then u can hv access right to enable and disable the api provided in android L – KOTIOS Oct 09 '14 at 04:13
  • @Nactive If you find my answare correct can you please check it? If not can you please explain why? Thanks! – Slv3r Apr 15 '15 at 14:50

4 Answers4

10

I've created this method looking around on internet; it works fine on rooted android 5.0.1 Basically you have to pass true if you want the connection to be enabled, false otherwise, and the context of your application.

private final static String COMMAND_L_ON = "svc data enable\n ";
private final static String COMMAND_L_OFF = "svc data disable\n ";
private final static String COMMAND_SU = "su";

public static void setConnection(boolean enable,Context context){

    String command;
    if(enable)
        command = COMMAND_L_ON;
    else
        command = COMMAND_L_OFF;        

    try{
        Process su = Runtime.getRuntime().exec(COMMAND_SU);
        DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());

        outputStream.writeBytes(command);
        outputStream.flush();

        outputStream.writeBytes("exit\n");
        outputStream.flush();
        try {
            su.waitFor();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        outputStream.close();
    }catch(IOException e){
        e.printStackTrace();
    }
}

Please report if this has problems on some device.

EDIT: Now also compatible with android 5.1 Credit

Community
  • 1
  • 1
Slv3r
  • 479
  • 1
  • 5
  • 15
3

Use this

TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
Method methodSet = tm.class.getDeclaredMethod( "setDataEnabled", boolean.class);
methodSet.invoke(tm, true); 

Edit: This requires permission MODIFY_PHONE_STATE, this is System or signature level permission.

Ideally you could create a runnable jar file with this code and execute it using

export CLASSPATH=<jar path>
exec app_process <jar-dir-path> your.package.name.classname "$@"

from su shell.

nandeesh
  • 24,740
  • 6
  • 69
  • 79
  • Did you test this in Android L? It makes no sense setting the method to NOT accessible and then invoking it. – Flyview Oct 14 '14 at 15:03
  • This requires permission MODIFY_PHONE_STATE which is only granted to system apps. Is there a way to grant this with root access? – Flyview Oct 18 '14 at 17:17
  • if you have root access, push your app to system/app , your app will become a system app – nandeesh Oct 20 '14 at 07:32
  • Is this something that can be done automatically by the app to itself? I don't want to have to get my users to do this manually. – Flyview Oct 21 '14 at 19:12
  • 3
    @nandeesh: Simply moving your app to the `/system/app` directory does not magically make your app a system app. You still need to sign your app with an Android platform certificate plus configure your `AndroidManifest.xml` with the appropriate directives in order for the app to run as a system app. I doubted that your answer above work at all, let alone being awarded 25 reputation from the bounty. – ChuongPham Nov 23 '14 at 07:34
  • @ChuongPham: This answer is incomplete - it needs to expand on how an app must be signed with an Android platform certificate, `AndroidManifest.xml` configurations, etc. Simply pushing the app to the **/system/app/ directory on a device is **not** going to make it a system app. –  Nov 23 '14 at 07:44
  • @ChuongPham do you even know how to sign, because to sign an app you dont need to change AndroidManifest.xml and signing is not a condition for system app, there are numerous system apps e.g carrier apps, google apps which are not platform signed, but they are system app. – nandeesh Nov 23 '14 at 09:37
  • @nandeesh: I would suggest you research first before posting wild comment as it shows that you do not understand about the fundamental basics regarding system apps, carrier apps, etc and how they operate within the security model of Android. – ChuongPham Nov 23 '14 at 16:23
3

I noticed that the service call method does not work consistently on all devices. The number to be used in it varied from device to device.

I have found the following solution which works without any issue across all ROOTED devices.

Simply execute the following via su

To enable mobile data

svc data enable

To disable mobile data

svc data disable

It's as simple as that.

A.J.
  • 1,520
  • 17
  • 22
0
void turnData(boolean ON) throws Exception
{

    int currentapiVersion = android.os.Build.VERSION.SDK_INT;
    if(currentapiVersion == Build.VERSION_CODES.FROYO)
    {

        Log.i("version:", "Found Froyo");
        try{ 
            Method dataConnSwitchmethod;
            Class telephonyManagerClass;
            Object ITelephonyStub;
            Class ITelephonyClass;
            TelephonyManager telephonyManager = (TelephonyManager) cx.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);

            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 (ON) {
             dataConnSwitchmethod = ITelephonyClass.getDeclaredMethod("enableDataConnectivity"); 

        } else {
            dataConnSwitchmethod = ITelephonyClass.getDeclaredMethod("disableDataConnectivity");
        }
        dataConnSwitchmethod.setAccessible(true);
        dataConnSwitchmethod.invoke(ITelephonyStub);
        }catch(Exception e){
              Log.e("Error:",e.toString());
        }

    }
     else
    {
       Log.i("version:", "Found Gingerbread+");
       final ConnectivityManager conman = (ConnectivityManager) cx.getApplicationContext().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, ON);
    }
}
Ali
  • 31
  • 4