Как получить доступ к setPreferredNetworkType в источнике Android - PullRequest
9 голосов
/ 25 марта 2011

У меня есть вопрос к вам, я пытаюсь выбрать предпочитаемый тип сети на моем телефоне Android.Как вы можете сделать, выполнив следующие действия:

  1. Наберите # # 4636 # #
  2. Выберите «Информация о телефоне»
  3. Go bottom
  4. Выберите предпочитаемый тип сети в меню

Итак, после некоторых поисков исходного кода я нашел правильный класс: Phone.java в (\ frameworks \ base \телефония \ java \ com \ android \ internal \ telephony)

Итак, с полезными советами Vinay : Как отключить мобильные данные на Android Кто использует отражение javaчтобы получить доступ к скрытым классам, я тоже пытался сделать:

Method setPrefNetmethod;
Class telephonyManagerClass;
Object ITelephonyStub;
Class ITelephonyClass;

TelephonyManager telephonyManager = (TelephonyManager)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());

setPrefNetmethod = ITelephonyClass.getDeclaredMethod("setPreferredNetworkType",new Class[] { Integer.class, Message.class });

Message response = Message.obtain();
setPrefNetmethod.setAccessible(false);

setPrefNetmethod.invoke(ITelephonyStub, new Object[] { network_mode, response });

Но проблема в том, что у меня эта ошибка на DDMS:

03-25 18: 18: 45.937: WARN / System.err (2989): java.lang.NoSuchMethodException: setPreferredNetworkType 03-25 18: 18: 45.937: WARN / System.err (2989): в java.lang.ClassCache.findMethodByName (ClassCache.java:308)

Итак, у вас есть идея получить доступ к setPreferredNetworkType или выбрать программно мой предпочтительный тип сети?

Для вобразование (в RILConstants.java):

/* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
int NETWORK_MODE_WCDMA_PREF     = 0; /* GSM/WCDMA (WCDMA preferred) */
int NETWORK_MODE_GSM_ONLY       = 1; /* GSM only */
int NETWORK_MODE_WCDMA_ONLY     = 2; /* WCDMA only */
int NETWORK_MODE_GSM_UMTS       = 3; /* GSM/WCDMA (auto mode, according to PRL)
                                        AVAILABLE Application Settings menu*/
int NETWORK_MODE_CDMA           = 4; /* CDMA and EvDo (auto mode, according to PRL)
                                        AVAILABLE Application Settings menu*/
int NETWORK_MODE_CDMA_NO_EVDO   = 5; /* CDMA only */
int NETWORK_MODE_EVDO_NO_CDMA   = 6; /* EvDo only */
int NETWORK_MODE_GLOBAL         = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
                                        AVAILABLE Application Settings menu*/
int PREFERRED_NETWORK_MODE      = NETWORK_MODE_WCDMA_PREF;

Ответы [ 5 ]

5 голосов
/ 22 августа 2011

Вот хорошее руководство по доступу к внутреннему API: https://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-1-introduction/

Исходя из собственного опыта, я могу сказать вам, что доступ в целом работает, но вы получите исключение времени выполнения, поскольку только системные приложения имеют разрешения для настройки предпочитаемого типа сети.

Это означает, что ваше приложение также должно быть установлено в системной папке И должно быть подписано системным ключом, который является сутью вопроса ...

1 голос
/ 24 апреля 2016

Вы можете попробовать это сообщение: http://www.josemauricio.net/?p=486

Он использует эти команды AT:

KitKat: echo "AT ^ SYSCONFIG = 13,1,1,2 \ r"> /dev / smd0

Lollipop: echo "AT + WS46 = 12 \ r"> / dev / umts_at0

Одной из основных проблем является поиск правильной команды и последовательного порта, используемых вашим устройством.

1 голос
/ 25 июля 2013

Вот немного хардкорного отражения https://github.com/TheMasterBaron/Toggle-2G

0 голосов
/ 18 июля 2018

Сначала вы должны добавить указанные ниже разрешения в манифесте;

<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" tools:ignore="ProtectedPermissions"/>

Затем используйте приведенный ниже код для настройки предпочитаемой сети (обратите внимание, что ваше приложение должно иметь подпись OEM [Системное разрешение], чтобы ниже работало);

public boolean setPreferredNetworkType(int networkType, int timeout) {
    Boolean result = false;
    try {
        TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
        final Method getPreferredNetworkType = telephonyManager.getClass().getDeclaredMethod("getPreferredNetworkType", int.class);
        final Method setPreferredNetworkType = telephonyManager.getClass().getDeclaredMethod("setPreferredNetworkType", int.class, int.class);
        final Method getSubId = telephonyManager.getClass().getDeclaredMethod("getSubId");
        getPreferredNetworkType.setAccessible(true);
        setPreferredNetworkType.setAccessible(true);
        getSubId.setAccessible(true);
        Integer currentNetworkType = (Integer) getPreferredNetworkType.invoke(telephonyManager, getSubId.invoke(telephonyManager));
        if (currentNetworkType != networkType) {
            setPreferredNetworkType.invoke(telephonyManager, getSubId.invoke(telephonyManager), networkType);
            while (timeout > 0) {
                currentNetworkType = (Integer) getPreferredNetworkType.invoke(telephonyManager, getSubId.invoke(telephonyManager));
                if (currentNetworkType == networkType) {
                    result = true;
                    break;
                }
                try {
                    Thread.sleep(THREAD_WAIT_TIMEOUT_IN_MS);
                } catch (InterruptedException e) {
                }
                timeout -= THREAD_WAIT_TIMEOUT_IN_MS;
            }
        } else {
            result = true;
        }
    } catch (SecurityException se) {
    } catch (Exception e) {
    }

    return result;
}

Вы можете использовать целочисленные значения RILConstants.java в качестве 'networkType'.

0 голосов
/ 10 августа 2016

Чтобы это работало, ваше приложение должно быть подписано системным ключом или иметь привилегию оператора. В противном случае приложение скинет java.lang.SecurityException: No modify permission or carrier privilege.

Мое приложение работает на Android 5.1 Lollipop (API 22) и подписано системным ключом, так что это единственная конфигурация, которую я могу убедиться, что она работает. Я не могу подтвердить подход с привилегиями оператора.

AndroidManifest.xml

Добавьте это разрешение в манифест приложения. Если вы используете Android Studio, он, вероятно, пометит эту строку как ошибку, потому что только системные приложения могут иметь это разрешение. Если вы можете подписать свое приложение системными ключами, не беспокойтесь.

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

Получить предпочтительную сеть

Возврат определяется в RILConstants.java, например RILConstants.NETWORK_MODE_WCDMA_PREF

public int getPreferredNetwork() {
    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;
}

Установить предпочтительный метод.

Параметр должен быть основан на RILConstants.java, например: RILConstants.NETWORK_MODE_LTE_ONLY

public void setPreferredNetwork(int networkType) {
    try {
        Method setPreferredNetwork = getHiddenMethod("setPreferredNetworkType",
                TelephonyManager.class, new Class[] {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();
    }
}

Это служебный метод для доступа к скрытым методам API.

/**
 * 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) {
    Method method = null;
    try {
        Class clazz = Class.forName(fromClass.getName());
        method = clazz.getMethod(methodName, params);
        method.setAccessible(true);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }

    return method;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...