Toggle mobile data programmatically on Android 4.4.2 - android

I've always used this code to enable mobile data programmatically:
ConnectivityManager conman = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
#SuppressWarnings("rawtypes")
final Class conmanClass = Class.forName(conman.getClass().getName());
final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
iConnectivityManagerField.setAccessible(true);
final Object iConnectivityManager = iConnectivityManagerField.get(conman);
#SuppressWarnings("rawtypes")
final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
#SuppressWarnings("unchecked")
final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
setMobileDataEnabledMethod.setAccessible(true);
setMobileDataEnabledMethod.invoke(iConnectivityManager, true);
This worked well, except now on Android 4.4.2 where I get this exception:
java.lang.NoSuchMethodException: setMobileDataEnabled [boolean]
at java.lang.Class.getConstructorOrMethod(Class.java:472)
at java.lang.Class.getDeclaredMethod(Class.java:640)
at com.test.auto3gPro.ClasseConnessione.settaConnessione(ClasseConnessione.java:48)
at com.test.auto3gPro.receiver.ScreenBroadcastReceiver.onReceive(ScreenBroadcastReceiver.java:108)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:768)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5081)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:781)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
Does anyone know how to fix this?

If you are using cyanogenmod the method setMobileDataEnabled(boolean) is changed in setMobileDataEnabled(String, boolean)...as you can see on this line of code.
So you can use the standard way and then in the NoSuchMethodException catch block try the "cyanogenmod" way like this:
Class[] cArg = new Class[2];
cArg[0] = String.class;
cArg[1] = Boolean.TYPE;
Method setMobileDataEnabledMethod;
setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", cArg);
Object[] pArg = new Object[2];
pArg[0] = getContext().getPackageName();
pArg[1] = true;
setMobileDataEnabledMethod.setAccessible(true);
setMobileDataEnabledMethod.invoke(iConnectivityManager, pArg);
I don't know if other mods are affected.

This worked for me on Android 4.4.4 release 2
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();
}
}
Reflection still works on the bleeding edge versions

Looks like you've discovered the danger of using reflection to play with internals of classes. I'm sure this wasn't exposed because enabling mobile data should be done by the user rather than by an application. If you really want to keep doing this, you'll have to look into the new source files of Android to find out the unexposed interfaces that you can discover at runtime and guard calls to this code by checks on the API level. I don't think I'd recommend programmatically changing mobile data though.

setMobileDataEnabled has been removed in Android L.
Use this instead:
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
Method methodSet = Class.forName(tm.getClass().getName()).getDeclaredMethod( "setDataEnabled", Boolean.TYPE);
methodSet.invoke(tm,true);
Make sure you have this permission on your manifest:
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
This permission is for System apps only

Related

How to Refresh my Mobile data network in android current version?

Kindly give answer,i have trouble to refresh mobile network,I don't want system app,I need only for android Mobile apps,I need to refresh my mobile data network pro grammatically in current version like marshmallow and nougat,I already put permissions for this,i attached following my codes
private static boolean setMobileConnectionEnabled(Context context, boolean enabled) {
try {
// Requires: android.permission.CHANGE_NETWORK_STATE
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
Log.i("if", "" + Build.VERSION.SDK_INT);
// pre-Gingerbread sucks!
final TelephonyManager telMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
final Method getITelephony = telMgr.getClass().getDeclaredMethod("getITelephony");
getITelephony.setAccessible(true);
final Object objITelephony = getITelephony.invoke(telMgr);
final Method toggleDataConnectivity = objITelephony.getClass()
.getDeclaredMethod(enabled ? "enableDataConnectivity" : "disableDataConnectivity");
toggleDataConnectivity.setAccessible(true);
toggleDataConnectivity.invoke(objITelephony);
}
// Requires: android.permission.CHANGE_NETWORK_STATE
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Log.i("else", "" + Build.VERSION.SDK_INT);
final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
// Gingerbread to KitKat inclusive
final Field serviceField = connMgr.getClass().getDeclaredField("mService");
serviceField.setAccessible(true);
final Object connService = serviceField.get(connMgr);
try {
final Method setMobileDataEnabled = connService.getClass()
.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
Log.i("try", "" + setMobileDataEnabled);
setMobileDataEnabled.setAccessible(true);
setMobileDataEnabled.invoke(connService, Boolean.valueOf(enabled));
} catch (NoSuchMethodException e) {
// Support for CyanogenMod 11+
final Method setMobileDataEnabled = connService.getClass()
.getDeclaredMethod("setMobileDataEnabled", String.class, Boolean.TYPE);
setMobileDataEnabled.setAccessible(true);
Log.i("catch", "" + setMobileDataEnabled);
Log.i("errr", "" + e.getMessage());
try {
setMobileDataEnabled.invoke(connService, context.getPackageName(), Boolean.valueOf(enabled));
} catch (InvocationTargetException e1) {
e1.printStackTrace();
}
}
}
// Requires: android.permission.MODIFY_PHONE_STATE (System only, here for completions sake)
else {
// Lollipop and into the Future!
final TelephonyManager telMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Log.i("telMgr",""+telMgr);
final Method setDataEnabled = telMgr.getClass().getDeclaredMethod("setDataEnabled", Boolean.TYPE);
Log.i("telMgdfgsdgr",""+setDataEnabled);
setDataEnabled.setAccessible(true);
setDataEnabled.invoke(telMgr, Boolean.valueOf(enabled));
}
return true;
} catch (NoSuchFieldException e) {
Log.e("", "setMobileConnectionEnabled", e);
} catch (IllegalAccessException e) {
Log.e("gsdjkghskd", "setMobileConnectionEnabled", e);
} catch (IllegalArgumentException e) {
Log.e("lllll", "setMobileConnectionEnabled", e);
} catch (NoSuchMethodException e) {
Log.e("nooooo", "setMobileConnectionEnabled", e);
} catch (InvocationTargetException e) {
Log.e("innnnnn", "setMobileConnectionEnabled", e);
}
return false;
}
My Manifest file
<permission
android:name="android.permission.READ_PHONE_STATE"
android:maxSdkVersion="24" />
<permission
android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="24" />
<permission
android:name="android.permission.MODIFY_PHONE_STATE"
android:maxSdkVersion="24" />
<permission
android:name="android.permission.CHANGE_NETWORK_STATE"
android:maxSdkVersion="24" />
Kindly give some suggestions please
I can't comment so I'll put my answer here, but it might disappoint you.
There's currently no way to do that in Android >= 5.
You can do that only on rooted phone or system app. It was possible through reflection but since it was #Hide annotated Google removed it and had every right to do so.
If you're looking for disabling only (or disabling the the possibility to change cellular data state) you can use your device provider's api (like Samsung). Samsung allows to disable the possibility to change the cell data state, but... you cannot force the state back to on, after the possibility to change was turned off.
Google repeatedly ignores tickets from the community to bring back this option to SDK.
Please downvote this answer only if you have a solution how to do that without rooted phone or system app.

Enable/Disable Data mobile programmatically - NO ROOT

I'm trying to enable/disable data mobile in specific moments. I've tried it on MotoG 4.4.2 (Rooted) with it I had no problem to do this, but when I've tried it on Samsung Galaxy Grand Prime 4.4.4 (No Root) it doesn't work, also I've tried it on Samsung Galaxy S3 4.3 (No Root) but it worked.
MotoG Worked -- WHY? -- ROOT Acces
Samsung Galaxy Grand Prime didn't work -- WHY? -- I think it doesn't work because when I try to do it manually I've to accept a dialog that I want to lose data connectivity, and I think this is the problem because it doesn't work.
Samsung Galaxy S3 worked -- WHY? -- I think it worked because the user put "Don't show me again" and user accepted it before.
The code that I'm trying is :
public void GetDataConnectionAPI() {
this.context.getApplicationContext();
TelephonyManager telephonyManager =
(TelephonyManager) this.context.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) {
e.printStackTrace();
}
}
And then I enable/disable the data with this method :
public void setMobileDataEnabled(Context context, boolean enabled) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final Class conmanClass = Class.forName(conman.getClass().getName());
final Field connectivityManagerField = conmanClass.getDeclaredField("mService");
connectivityManagerField.setAccessible(true);
final Object connectivityManager = connectivityManagerField.get(conman);
final Class connectivityManagerClass = Class.forName(connectivityManager.getClass().getName());
final Method setMobileDataEnabledMethod = connectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
setMobileDataEnabledMethod.setAccessible(true);
setMobileDataEnabledMethod.invoke(connectivityManager, enabled);
}
When I want to Enable I call this method :
public void EnableMobileData(){
try {
setMobileDataEnabled(context, true);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
On my Manifest I put
<!-- 3g uses-permisions-->
<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" />
I wonder if it's any possibility to avoid this dialog or just accept it programmatically..
I've read Bojan Kogoj answer that sais that I've to :
Pre-installed into a system folder on the ROM
Compiled by a manufacturer using their security certificate
But I'm wondering if is any other way to do this.
The MODIFY_PHONE_STATE permission is not guaranteed to work in all cases. By default it is a system-level permission, so it will only work on devices whose manufacturers have enabled it.
Similarly, methods like getITelephony() are device/manufacturer-specific, and there is no way to get the name of the methods for doing so on every device.
Unfortunately there is no guaranteed way to do this.

How to create the wifi tethering without sharing the internet connection(Hotspot) in android?

I'm having android(OS_VERSION 4.0) device. I would like to share the files to another android device through the wifi networks. I know, This can be done through wifi p2p(WifiDirect) in android 4.0 above. But this is not possible in android 2.3.3 devices(Prior to Android 4.0). I found the Superbeam application does the file sharing through shared networks in android 2.3.3.This application create the wifi tethering without sharing the internet connection of the device. The created tethering is only used for sharing the files not for sharing the internet. How to achieve this concept. Can anyone help me?
This answer may help to someone having the same question. The simple logic i implemented is,
1.Create the wifi tethering(Hotspot)
2.Disable the mobile data connection
Code is,
//To enable the wifi hotspot
setWifiTetheringEnabled(true);
//To disable the mobile data cnnection
setMobileDataEnabled(false);
private void setWifiTetheringEnabled(boolean enable) {
WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
Method[] methods = wifiManager.getClass().getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals("setWifiApEnabled")) {
try {
method.invoke(wifiManager, null, enable);
} catch (Exception ex) {
}
break;
}
}
}
private void setMobileDataEnabled(Context context, boolean enabled) {
try {
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);
} catch (ClassNotFoundException | NoSuchFieldException
| IllegalAccessException | IllegalArgumentException
| NoSuchMethodException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Disable/Enable mobile data on Android L with root access

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

Turn on/off mobile network connection programmatically in android jelly bean

I am using below code to turn on/off mobile network.
final ConnectivityManager conman = (ConnectivityManager) 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);
I tested this code with Android 2.3.X, 4.0.X and 4.1.X. It is working with only 2.3.X and 4.0.X but failed with 4.1.X.
I am getting java.lang.NoSuchFieldException: mService exception while testing with Android Jelly Bean.
Is there any other solution to my problem? I added all required permissions in manifest file.
try
{
dataMtd = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", boolean.class);
}
catch (SecurityException e1)
{
e1.printStackTrace();
}
catch (NoSuchMethodException e1)
{
e1.printStackTrace();
}
dataMtd.setAccessible(true);
try {
dataMtd.invoke(conm,true);
}
}
Where datamtd is a method.. Try with this my friend. I found it successful in my previous app. Hope this may help you. Sorry if not, since I'm not much experienced.:)

Categories

Resources