Skip to content Skip to sidebar Skip to footer

Change Mobile Network Mode (gsm, Wcdma, Auto)

I want to change the preferred network mode ie. gsm or wcdma or auto, programmatically, from code, on Android. Is this possible, and if so how ?

Solution 1:

It is possible, I did it.

For this to work, your app must be signed with the system key or have carrier privilege. Otherwise the app will throw java.lang.SecurityException: No modify permission or carrier privilege.

My app runs on Android 5.1 Lollipop(API 22) and is signed with the system key, so this is the only configuration I can confirm for sure that works. I can't confirm the carrier privilege approach.

AndroidManifest.xml

Add this permission to your app manifest. If you are using Android Studio, it will probably mark this line as an error because only system apps can have this permission. If you can sign your app with the system keys, don't worry.

<uses-permissionandroid:name="android.permission.MODIFY_PHONE_STATE"/>

Get Preferred Network

The return is defined in RILConstants.java, e.g. RILConstants.NETWORK_MODE_WCDMA_PREF

publicintgetPreferredNetwork() {
    Method method = getHiddenMethod("getPreferredNetworkType", TelephonyManager.class, null);
    int preferredNetwork = -1000;
    try {
        preferredNetwork = (int) method.invoke(mTelephonyManager);
        Log.i(TAG, "Preferred Network is ::: " + preferredNetwork);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }

    return preferredNetwork;
}

Set Preferred Method.

The parameter must be based on RILConstants.java, e.g.: RILConstants.NETWORK_MODE_LTE_ONLY

publicvoid setPreferredNetwork(int networkType) {
    try {
        Method setPreferredNetwork = getHiddenMethod("setPreferredNetworkType",
                TelephonyManager.class, newClass[] {int.class});
        Boolean success = (Boolean)setPreferredNetwork.invoke(mTelephonyManager,
                networkType);
        Log.i(TAG, "Could set Network Type ::: " + (success.booleanValue() ? "YES" : "NO"));
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

This is an utility method to access the hidden API methods.

/**
 * Get a hidden method instance from a class
 * @param methodName The name of the method to be taken from the class
 * @param fromClass The name of the class that has the method
 * @return A Method instance that can be invoked
 */public Method getHiddenMethod(String methodName, Class fromClass, Class[] params) {
    Methodmethod=null;
    try {
        Classclazz= Class.forName(fromClass.getName());
        method = clazz.getMethod(methodName, params);
        method.setAccessible(true);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }

    return method;
}

Solution 2:

Answer is NO

We can open directly the settings app of mobile network settings to switch between "2G" and "allow 3G" networks.A direct switch is sadly not possible.

We can develop something which will show current network and allow user short-cut from the app where they can switch network.

Solution 3:

This is not an answer, but expanding on Tulio-F's answer.

The RILConstants.java contain the following:

// NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE intNETWORK_MODE_WCDMA_PREF=0;   // GSM/WCDMA (WCDMA preferred) intNETWORK_MODE_GSM_ONLY=1;   // GSM only intNETWORK_MODE_WCDMA_ONLY=2;   // WCDMA only intNETWORK_MODE_GSM_UMTS=3;   // GSM/WCDMA (auto mode, according to PRL)**    intNETWORK_MODE_CDMA=4;   // CDMA and EvDo (auto mode, according to PRL)**intNETWORK_MODE_CDMA_NO_EVDO=5;   // CDMA only intNETWORK_MODE_EVDO_NO_CDMA=6;   // EvDo only intNETWORK_MODE_GLOBAL=7;   // GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)**intNETWORK_MODE_LTE_CDMA_EVDO=8;   // LTE, CDMA and EvDo intNETWORK_MODE_LTE_GSM_WCDMA=9;   // LTE, GSM/WCDMA intNETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA=10;  // LTE, CDMA, EvDo, GSM/WCDMA intNETWORK_MODE_LTE_ONLY=11;  // LTE Only mode. intNETWORK_MODE_LTE_WCDMA=12;  // LTE/WCDMA intNETWORK_MODE_TDSCDMA_ONLY=13;  // TD-SCDMA only intNETWORK_MODE_TDSCDMA_WCDMA=14;  // TD-SCDMA and WCDMA intNETWORK_MODE_LTE_TDSCDMA=15;  // TD-SCDMA and LTE intNETWORK_MODE_TDSCDMA_GSM=16;  // TD-SCDMA and GSM intNETWORK_MODE_LTE_TDSCDMA_GSM=17;  // TD-SCDMA,GSM and LTE intNETWORK_MODE_TDSCDMA_GSM_WCDMA=18;  // TD-SCDMA, GSM/WCDMA intNETWORK_MODE_LTE_TDSCDMA_WCDMA=19;  // TD-SCDMA, WCDMA and LTE intNETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA=20;  // TD-SCDMA, GSM/WCDMA and LTE intNETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA=21;  // TD-SCDMA,EvDo,CDMA,GSM/WCDMAintNETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA=22;  // TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDointPREFERRED_NETWORK_MODE= SystemProperties.getInt("ro.telephony.default_network", NETWORK_MODE_WCDMA_PREF);

Where:

** = "AVAILABLE Application Settings menu"

Solution 4:

For those still looking at this and can not signe their app with the system key.

You might want to use the startActivityForResult method to redirect the user to a peculiar activity_code.

Some of these codes are not guaranteed with a matching activity (Due to the different flavours of Android)

In kotlin you could use something like this :

startActivityForResult(Intent(android.provider.Settings.ACTION_NETWORK_OPERATOR_SETTINGS), 0)

of course don't forget to import the required libraries.

Remember that the user will have to navigate a bit into the menu. So maybe put some generic and textual explanation about the inputs/actions the user should do to land on the good settings page.

note1: it is possible that on some devices there is no implementations for choosing the prefered network.

note2: I would definitely recommand Tulio F. solution if you can obtain according privilegies.

Post a Comment for "Change Mobile Network Mode (gsm, Wcdma, Auto)"