androidandroid-networkingairplane-mode

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.


Solution

  • 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"/>