Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reset Android mobile network signal?

I need my app to reset the device's mobile network signal. This would have the same effect as toggling airplane mode where connectivity is temporarily lost, a new IP address is assigned upon reconnection, and the LTE/signal icon in the status bar should disappear and then reappear upon reconnection. I found an app on the Play Store that I tested on my phone running Android 4.4.4 with CyanogenMod and it does exactly this, but I am unsure as to how I can implement this in my own app. I think it's related to the CHANGE_NETWORK_STATE permission. I am seeking documentation or some simple example code that will reset the network connection.

Note that I am not specifically trying to toggle airplane mode, but rather to reset the mobile data in the way that the app linked above does, as I have tested that it indeed works without even requiring root privileges.

like image 671
Keavon Avatar asked Sep 28 '22 22:09

Keavon


2 Answers

Lollipop support requires a new System level privledge android.permission.MODIFY_PHONE_STATE to work.

private static boolean setMobileConnectionEnabled(Context context, boolean enabled)
{
    try{
        // Requires: android.permission.CHANGE_NETWORK_STATE
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD){
            // 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){
            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);
                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);
                setMobileDataEnabled.invoke(connService, context.getPackageName(), Boolean.valueOf(enabled));
            }
        }
        // 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);
            final Method setDataEnabled = telMgr.getClass().getDeclaredMethod("setDataEnabled", Boolean.TYPE);
            setDataEnabled.setAccessible(true);
            setDataEnabled.invoke(telMgr, Boolean.valueOf(enabled));
        }
        return true;
    }
    catch(NoSuchFieldException e){
        Log.e(TAG, "setMobileConnectionEnabled", e);
    }
    catch(IllegalAccessException e){
        Log.e(TAG, "setMobileConnectionEnabled", e);
    }
    catch(IllegalArgumentException e){
        Log.e(TAG, "setMobileConnectionEnabled", e);
    }
    catch(NoSuchMethodException e){
        Log.e(TAG, "setMobileConnectionEnabled", e);
    }
    catch(InvocationTargetException e){
        Log.e(TAG, "setMobileConnectionEnabled", e);
    }
    return false;
}

Permission required.

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
like image 133
Simon Avatar answered Oct 03 '22 00:10

Simon


Starting with 4.4.2, one can no longer acquire permissions to toggle airplane mode or mobile data. However, using reflection, one can work around that limitation.

Here's how to toggle airplane mode: Toggle airplane mode in Android

Here's a method to toggle mobile data pre 4.4.2 and post (using reflection): Toggle mobile data programmatically on Android 4.4.2

Note, I found all that in less than 3 minutes by searching on my favorite search engine for "android toggle airplane mode" and "android toggle mobile data".

Note 2: You can use reflection for airplane mode toggling too, but you may need to do some digging to find the necessary ASOP API or see if someone else (like CyanogenMod) has already done it.

like image 41
iheanyi Avatar answered Oct 03 '22 02:10

iheanyi