НеsetMobileDataEnabled метод больше не вызываемый по состоянию на Android L, а затем

? ChuongPham @ | Original: StackOverFlow
---

Я вошел https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=78084 с Google в отношении способа setMobileDataEnabled() не будучи больше не вызываемый с помощью отражения. Это было выкупу с Android 2.1 (API 7) Android 4.4 (API 19 ) посредством отражения, но по состоянию на Android л и позже, даже с корнем ,метод setMobileDataEnabled() не вызвать.

Официальный ответ, чтовопрос "закрытое " истатус установлен в положение " WorkingAsIntended " . Простое объяснение Google заключается в следующем:

Частные API, являются частными, поскольку они не являются стабильными и могут исчезнуть без предварительного уведомления.

Да, Google, мы осознаем риск, используя отражение позвонить скрыты методично еще до Android вышел на scene-, но вы должны обеспечить более точный ответ, чтобы альтернатив, если таковые имеются, для достижения того же результата, как setMobileDataEnabled() . (Если вы недовольны решением Google, как и я, то войти в https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=78084 и звезды это как можно больше, чтобы Google знаем ошибку своем пути. )

Итак, мой вопрос к вам : Мы в тупике, когда дело доходит до программно включить или отключить функцию мобильной сети на Android устройство? Это жесткий подход из Google как-то не очень хорошо сидеть со мной . Если у вас есть обходной путь для Android 5.0 ( Lollipop ) и за его пределами, я хотел бы услышать ваше ответа / обсуждение в этой теме .

Я использовал код ниже, чтобы увидеть, еслиsetMobileDataEnabled() метод доступен :

final Class<?> conmanClass = Class.forName(context.getSystemService(Context.CONNECTIVITY_SERVICE).getClass().getName());
final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
iConnectivityManagerField.setAccessible(true);
final Object iConnectivityManager = iConnectivityManagerField.get(context.getSystemService(Context.CONNECTIVITY_SERVICE));
final Class<?> iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
final Method[] methods = iConnectivityManagerClass.getDeclaredMethods();
for (final Method method : methods) {
    if (method.toGenericString().contains("set")) {
        Log.i("TESTING", "Method: " + method.getName());
    }
}

Но это не так.

UPDATE : В настоящее время, это возможность переключать сети мобильной связи, еслиустройство корни. Тем не менее, для некорневых устройств, это все-такипроцесс расследования, так как не существует универсального метода для переключения сети мобильной связи .

---

Top 5 ответ

1Muzikant @

Просто поделитьсяеще несколько идеи и возможное решение (для корневых устройств и системных приложений ).

Solution #1

Похоже,setMobileDataEnabled метод больше не существует в ConnectivityManager и эта функциональность была перемещена в TelephonyManager с двумя методами getDataEnabled и setDataEnabled . Я пыталась дозвониться эти методы с отражением, как вы можете видеть в коде ниже :

public void setMobileDataState(boolean mobileDataEnabled)
{
    try
    {
        TelephonyManager telephonyService = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

        Method setMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod("setDataEnabled", boolean.class);

        if (null != setMobileDataEnabledMethod)
        {
            setMobileDataEnabledMethod.invoke(telephonyService, mobileDataEnabled);
        }
    }
    catch (Exception ex)
    {
        Log.e(TAG, "Error setting mobile data state", ex);
    }
}

public boolean getMobileDataState()
{
    try
    {
        TelephonyManager telephonyService = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

        Method getMobileDataEnabledMethod = telephonyService.getClass().getDeclaredMethod("getDataEnabled");

        if (null != getMobileDataEnabledMethod)
        {
            boolean mobileDataEnabled = (Boolean) getMobileDataEnabledMethod.invoke(telephonyService);

            return mobileDataEnabled;
        }
    }
    catch (Exception ex)
    {
        Log.e(TAG, "Error getting mobile data state", ex);
    }

    return false;
}

При выполнении кода вы получитеSecurityException о том, что Neither user 10089 nor current process has android.permission.MODIFY_PHONE_STATE.

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

(начало напыщенную речь : что страшного android.permission.MODIFY_PHONE_STATE разрешения ... конец разглагольствовать ).

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

Solution #2

Для проверки текущего состояния мобильной передачи данных можно использовать mobile_data Поле Settings.Global (не описаны в официальной документации ) .

Settings.Global.getInt(contentResolver, "mobile_data");

И, чтобы включить / отключить мобильный данные, которые вы можете использовать команды на укоренившихся устройств ( только с основными испытаний, проведенных поэтому любая обратная связь в комментариях ценится ) . Вы можете запустить следующую команду (ы) в качестве корневого ( 1 = включить, 0 = отключить) :

settings put global mobile_data 1
settings put global mobile_data 0
2ChuongPham @

Чтобы продлить Музыкант в Решение # 2, может кто-то пожалуйста, попробуйте ниже раствора на Android 5.0 корнями устройства (как я в настоящее время не имеют один), и дайте мне знать, если он работает или не работает .

Чтобы включить или отключить мобильные данные, попробуйте:

// 1: Enable; 0: Disable
su -c settings put global mobile_data 1
su -c am broadcast -a android.intent.action.ANY_DATA_STATE --ez state 1

Примечание:mobile_data переменная может быть найден в Android API 21 исходных кодов на /android-sdk/sources/android-21/android/provider/Settings.java и объявлен как :

/**
 * Whether mobile data connections are allowed by the user.  See
 * ConnectivityManager for more info.
 * @hide
*/
public static final String MOBILE_DATA = "mobile_data";

В то время какandroid.intent.action.ANY_DATA_STATE Намерение может быть найден в Android API 21 исходных кодов на /android-sdk/sources/android-21/com/android/internal/telephony/TelephonyIntents.java и объявлен как :

/**
 * Broadcast Action: The data connection state has changed for any one of the
 * phone's mobile data connections (eg, default, MMS or GPS specific connection).
 *
 * <p class="note">
 * Requires the READ_PHONE_STATE permission.
 * <p class="note">This is a protected intent that can only be sent by the system.
 *
 */
public static final String ACTION_ANY_DATA_CONNECTION_STATE_CHANGED
        = "android.intent.action.ANY_DATA_STATE";

UPDATE 1 : Если вы не хотите осуществлять вышеуказанные коды Java в вашем Android приложения, а затем вы можете запуститьsu команды через оболочки ( Linux) или из командной строки (Windows ), как следующим образом:

adb shell "su -c 'settings put global mobile_data 1; am broadcast -a android.intent.action.ANY_DATA_STATE --ez state 1'"

Примечание: adb находится на /android-sdk/platform-tools/ каталог. Команда settings поддерживается только на Android 4.2 или более поздней версии. Старая Android версия будет сообщить "sh: settings: not found" ошибку.

UPDATE 2 : Еще один способ для переключения сети мобильной связи на корни Android 5+ устройства будет использовать service команду оболочки недокументированные . Следующая команда может быть выполнена с помощью АБР для переключения сети мобильной связи :

// 1: Enable; 0: Disable
adb shell "su -c 'service call phone 83 i32 1'"

Or just:

// 1: Enable; 0: Disable
adb shell service call phone 83 i32 1

Примечание: adb находится на /android-sdk/platform-tools/ каталог. Если вы не хотите использовать АБР, выполнения метода с помощью su в вашем приложении .

3rgruet @

Решение # 1 из Музыкант, кажется, работает, если вы делаете приложение " системы ", перемещая .apk в папку /system/priv-app/, а не к /system/app/ одного ( jaumard : может быть, поэтому ваш тест не работает) .

Когда.apk в папку /system/priv-app/, она может успешно запроситьужасно android.permission.MODIFY_PHONE_STATE разрешение вManifest и вызвать TelephonyManager.setDataEnabled и TelephonyManager.getDataEnabled .

По крайней мере, работает на Nexus 5 / Android 5.0. В .apk завивки являются 0144 . Вы должны перезагрузить устройство дляизменения должны быть приняты во внимание, может быть, это можно было бы избежать - см http://stackoverflow.com/questions/26487750/android-5-0-lollipop-force-rescan-of-system- собств - приложение.

4Sahil Lombar @

Чтобы исправить Музыкант Решение # 2

settings put global mobile_data 1

Ли включить только тумблер для мобильных данных, но ничего не делает для подключения. Толькопереключения включен. Для того, чтобы получить данные работы, используя

su -c am broadcast -a android.intent.action.ANY_DATA_STATE --ez state 1

Дает ошибку, какдополнительный для

android.intent.action.ANY_DATA_STATE

Требуется объект строки, а --ez параметр используется для логических . Ref: PhoneGlobals.java и усилитель ; PhoneConstants.java . После использования подключения или подключен в качестве дополнительного помощью команды

su -c am broadcast -a android.intent.action.ANY_DATA_STATE --es state connecting

Тем не менее не вижу никаких включить данные.