0

With the help of below link i tried to write code for Enabling/Disabling Data.

http://stackoverflow.com/questions/23100298/android-turn-on-off-mobile-data-using-code

But while running the code i am getting java.lang.NoSuchMethodException

Main Code :

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.content.Context;
import android.net.ConnectivityManager;
import android.telephony.TelephonyManager;
import android.util.Log;


//the method below enables/disables mobile data depending on the Boolean 'enabled' parameter.
        public void setMobileDataEnabled(Context context, boolean enabled) {
            this.context = context;
            //create instance of connectivity manager and get system connectivity service
                final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                 try {
                    //create instance of class and get name of connectivity manager system service class
                     Class conmanClass = Class.forName(conman.getClass().getName());
                    //create instance of field and get mService Declared field 
                    final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
                  //Attempt to set the value of the accessible flag to true
                    iConnectivityManagerField.setAccessible(true);
                  //create instance of object and get the value of field conman
                    final Object iConnectivityManager = iConnectivityManagerField.get(conman);
                    //create instance of class and get the name of iConnectivityManager field
                    final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
                  //create instance of method and get declared method and type
                    final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled",Boolean.TYPE);
                    //Attempt to set the value of the accessible flag to true
                    setMobileDataEnabledMethod.setAccessible(true);
                  //dynamically invoke the iConnectivityManager object according to your need (true/false)
                    setMobileDataEnabledMethod.invoke(iConnectivityManager, enabled);
                    //Thread.sleep(1000L);
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (NoSuchFieldException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                   Log.d("POST", "Method not found");
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }

        // below method returns true if mobile data is on and vice versa
         public boolean mobileDataEnabled(Context context){
                boolean mobileDataEnabled = false; // Assume disabled
                ConnectivityManager cm = (ConnectivityManager)   context.getSystemService(Context.CONNECTIVITY_SERVICE);
                try {
                    Class cmClass = Class.forName(cm.getClass().getName());
                    Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
                    method.setAccessible(true); // Make the method callable
                    // get the setting for "mobile data"
                    mobileDataEnabled = (Boolean)method.invoke(cm);
                } catch (Exception e) {
                    // Some problem accessible private API
                    // TODO do whatever error handling you want here
                }
                return mobileDataEnabled;
            }

Not able to figure it out where i am missing something .Can anybody point out to me the missing point here in the code.

Error:

01-03 06:18:05.549: W/System.err(5663): java.lang.NoSuchMethodException: setMobileDataEnabled [boolean]
01-03 06:18:05.559: W/System.err(5663):     at java.lang.Class.getConstructorOrMethod(Class.java:472)
01-03 06:18:05.559: W/System.err(5663):     at java.lang.Class.getDeclaredMethod(Class.java:640)
01-03 06:18:05.559: W/System.err(5663):     at Core.MobileDataNetwrokHandler.setMobileDataEnabled(MobileDataNetwrokHandler.java:129)
01-03 06:18:05.559: W/System.err(5663):     at com.test.post.MainActivity.mobileData(MainActivity.java:59)
01-03 06:18:05.559: W/System.err(5663):     at java.lang.reflect.Method.invokeNative(Native Method)
01-03 06:18:05.559: W/System.err(5663):     at java.lang.reflect.Method.invoke(Method.java:515)
01-03 06:18:05.559: W/System.err(5663):     at android.view.View$1.onClick(View.java:3818)
01-03 06:18:05.559: W/System.err(5663):     at android.view.View.performClick(View.java:4438)
01-03 06:18:05.559: W/System.err(5663):     at android.view.View$PerformClick.run(View.java:18439) 
user3688062
  • 53
  • 1
  • 11
  • That's because the method is not exported, hence you cannot call it - even via Reflection. I'm guessing you're getting the above error with an Android L emulator huh? – ChuongPham Sep 19 '14 at 14:09
  • @ChuongPham What does it mean for a method not to be exported? Can you please email me at teqtic@gmail.com? I would really like to find a solution. – Flyview Sep 26 '14 at 22:01
  • @Flyview: Instead of mailing my response to you personally, I'll post my comment here so others can read it. When Google engineers build a release of an Android firmware (e.g. Android L), the release will have exported public methods (i.e. `public` identifier), or private/hidden methods (i.e. declared as `private` and/or marked with `@hide` identifier). A hidden method can then be acccessed via Refletion by third-party apps. _So, if a method is not exported with the firmware, then it does not exist._ So, using Reflection to call such method will return `NoSuchMethodException`. That's it. – ChuongPham Sep 27 '14 at 06:26
  • @ChuongPham So then basically, the method isn't there! Why is it in the grep code source? We need to figure out how ConnectivityManager toggles data now. – Flyview Sep 27 '14 at 13:21
  • @Flyview: There's no solution unless someone logs a request with Google to have the `setMobileDataEnabled` method exported, even if it is hidden, so we can use Reflection to call it. – ChuongPham Sep 27 '14 at 13:34
  • @ChuongPham well how does Android set mobile data enabled now without this method? That's what we need to figure out. – Flyview Sep 28 '14 at 13:28

1 Answers1

1

To see if a method of the ConnectivityManager class is callable via Reflection, try this:

final Class<?> conmanClass = Class.forName(GlobalService.getConnectivityService(context).getClass().getName());
final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
iConnectivityManagerField.setAccessible(true);
final Object iConnectivityManager = iConnectivityManagerField.get(GlobalService.getConnectivityService(context));
final Class<?> iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
final Method[] methods = iConnectivityManagerClass.getDeclaredMethods();
for (final Method method : methods) {
    if (method.toGenericString().contains("set")) {
        Log.i("TESTING", "Method: " + method.getName());
    }
}

If the method does not exist (for example, setMobileDataEnabled) in the LogCat output, then it's not callable.

ChuongPham
  • 4,761
  • 8
  • 43
  • 53