Переключить режим полета в Android

Я сделал ошибку? Это не работает.

public void airplane() {
    boolean isEnabled = Settings.System.getInt(this.getApplicationContext().getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) == 1;
    Settings.System.putInt(context.getContentResolver(),Settings.System.AIRPLANE_MODE_ON,isEnabled ? 0 : 1);
    //Settings.System.putInt(this.getApplicationContext().getContentResolver(),Settings.System.AIRPLANE_MODE_ON,isEnabled ? 0 : 1);
    Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
}

10 ответов

Решение

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

Адаптировано из режима управления самолетом:

// read the airplane mode setting
boolean isEnabled = Settings.System.getInt(
      getContentResolver(), 
      Settings.System.AIRPLANE_MODE_ON, 0) == 1;

// toggle airplane mode
Settings.System.putInt(
      getContentResolver(),
      Settings.System.AIRPLANE_MODE_ON, isEnabled ? 0 : 1);

// Post an intent to reload
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", !isEnabled);
sendBroadcast(intent);

Работает для всех версий API.

  • переключить автоматически для API < 17
  • открыть режим "Активность самолета" по умолчанию для действий пользователя для API >= 17

нет рута, нет системного разрешения!


в AndroidManifest.xml добавить разрешение:

<!--airplane mode-->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>

затем:

@SuppressWarnings("deprecation")
    private void initAirplanemodeBtn() {
        airplanemodeButton = (ToggleButton) findViewById(R.id.airplanemode_btn);
        airplanemodeButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                if (android.os.Build.VERSION.SDK_INT < 17) {
                    try {
                        // read the airplane mode setting
                        boolean isEnabled = Settings.System.getInt(
                                getContentResolver(),
                                Settings.System.AIRPLANE_MODE_ON, 0) == 1;

                        // toggle airplane mode
                        Settings.System.putInt(
                                getContentResolver(),
                                Settings.System.AIRPLANE_MODE_ON, isEnabled ? 0 : 1);

                        // Post an intent to reload
                        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
                        intent.putExtra("state", !isEnabled);
                        sendBroadcast(intent);
                    } catch (ActivityNotFoundException e) {
                        Log.e(TAG, e.getMessage());
                    }
                } else {
                    try {
                        Intent intent = new Intent(android.provider.Settings.ACTION_AIRPLANE_MODE_SETTINGS);
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);
                    } catch (ActivityNotFoundException e) {
                        try {
                            Intent intent = new Intent("android.settings.WIRELESS_SETTINGS");
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                        } catch (ActivityNotFoundException ex) {
                            Toast.makeText(buttonView.getContext(), R.string.not_able_set_airplane, Toast.LENGTH_SHORT).show();
                        }
                    }
                }

            }
        });
    }

Следующее может быть использовано на рутированном устройстве.

Из командной строки вы можете включить / выключить режим полета следующим образом:

ON:
settings put global airplane_mode_on 1
am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true

OFF:
settings put global airplane_mode_on 0
am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false

Это работает с Android 4.4.2+

Я думаю, что "Settings.System.AIRPLANE_MODE_ON" устарела, я использую:

public class AirplaneModeService {
    public boolean run(Context context) {
        boolean isEnabled = isAirplaneModeOn(context);
        // Toggle airplane mode.
        setSettings(context, isEnabled?1:0);
        // Post an intent to reload.
        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        intent.putExtra("state", !isEnabled);
        context.sendBroadcast(intent);
        return true;
    }
    public static boolean isAirplaneModeOn(Context context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            return Settings.System.getInt(context.getContentResolver(), 
                    Settings.System.AIRPLANE_MODE_ON, 0) != 0;          
        } else {
            return Settings.Global.getInt(context.getContentResolver(), 
                    Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
        }       
    }
    public static void setSettings(Context context, int value) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
            Settings.System.putInt(
                      context.getContentResolver(),
                      Settings.System.AIRPLANE_MODE_ON, value);
        } else {
            Settings.Global.putInt(
                      context.getContentResolver(),
                      Settings.Global.AIRPLANE_MODE_ON, value);
        }       
    }
}

Я надеюсь, что это поможет кому-то.

Как упомянул @eggyal, переключение в режим полета невозможно с версии 4.2 и выше.

Но что мы можем сделать, это включить каждую из беспроводных услуг:

Wifi можно контролировать с помощью WifiService ~ getSystemService(Context.WIFI_SERVICE). Bluetooth можно контролировать с помощью BluetoothAdapter- getSystemService(Context.BLUETOOTH_SERVICE).

После некоторых исследований я обнаружил, что с помощью Java Reflection вы все еще можете управлять Android-радио (Wifi, сеть, Bluetooth), и в основном режим полета - переключать состояние Bluetooth, Wifi и сетей.

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

ВНИМАНИЕ: Использование Reflection может не работать на некоторых устройствах (зависит от реализации классов производителем).

Этот пример кода включает мобильную сеть:

private void setMobileRadioEnabled(boolean enabled) {
    try {
        final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        final Class conmanClass = Class.forName(conman.getClass().getName());
        final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
        iConnectivityManagerField.setAccessible(true);
        final Object iConnectivityManager = iConnectivityManagerField.get(conman);
        final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
        final Method setRadio = iConnectivityManagerClass.getDeclaredMethod("setRadio", Integer.TYPE ,  Boolean.TYPE);
        setRadio.setAccessible(true);
        for (NetworkInfo networkInfo : conman.getAllNetworkInfo()) {
            if(isNetworkTypeMobile(networkInfo.getType())) {
                setRadio.invoke(iConnectivityManager, networkInfo.getType(), enabled);
            }
        }
    } catch (Exception e) {
        Log.e(TAG, "Opss...", e);
    }
}

public static boolean isNetworkTypeMobile(int networkType) {
    switch (networkType) {
        case ConnectivityManager.TYPE_MOBILE:
        case ConnectivityManager.TYPE_MOBILE_MMS:
        case ConnectivityManager.TYPE_MOBILE_SUPL:
        case ConnectivityManager.TYPE_MOBILE_DUN:
        case ConnectivityManager.TYPE_MOBILE_HIPRI:
        case 10:
        case 11:
        case 12:
        case 14:
            return true;
        default:
            return false;
    }
}

После леденца на палочке, вы можете использовать метод ниже, но это скрытый API, и ваше приложение требует разрешения на уровне системы

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

ConnectivityManager mgr =  (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
        mgr.setAirplaneMode(true); 

Здесь перед каждой настройкой используйте android.provider следующим образом:

public class MainActivity extends Activity implements OnClickListener {

    Button air;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        air = (Button) findViewById(R.id.button1);
        air.setOnClickListener(this);
    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        // read the airplane mode setting
        boolean isEnabled = android.provider.Settings.System.getInt(
              getContentResolver(), 
              android.provider.Settings.System.AIRPLANE_MODE_ON, 0) == 1;

        // toggle airplane mode
        android.provider.Settings.System.putInt(
              getContentResolver(),
              android.provider.Settings.System.AIRPLANE_MODE_ON, isEnabled ? 0 : 1);

        // Post an intent to reload
        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        intent.putExtra("state", !isEnabled);
        sendBroadcast(intent);

    }

}

Обратите внимание, что, как описано в API Android 4.2 (выделение добавлено):

Новые глобальные настройки

Системные настройки были обновлены для поддержки нескольких пользователей с добавлением Settings.Global, Этот набор настроек похож на Settings.Secure настройки, потому что они доступны только для чтения, но применяются глобально ко всем пользовательским пространствам на устройстве.

Несколько существующих настроек были перенесены сюда из Settings.System или же Settings.Secure, Если ваше приложение вносит изменения в настройки, ранее определенные в Settings.System(такие как AIRPLANE_MODE_ON), то следует ожидать, что это больше не будет работать на устройстве под управлением Android 4.2 или выше, если эти настройки были перенесены в Settings.Global, Вы можете продолжить читать настройки, которые находятся в Settings.Global, но поскольку настройки больше не считаются безопасными для изменения приложений, попытка сделать это молча провалится, и система запишет предупреждение в системный журнал при запуске приложения на Android 4.2 или выше.

Этот работает для меня

public static boolean isAirplaneModeOn() {
    return Settings.System.getInt(mContext.getContentResolver(),
            Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}

public static void setAirPlaneMode(boolean airplaneMode) {
    Logger.d(LOG_TAG + "setAirPlaneMode airplaneMode: " + airplaneMode) ;
    int state = airplaneMode ? 1 : 0;
    Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON,
                             state);
    Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
    intent.putExtra("state", state);
    mContext.sendBroadcast(intent);
}

Но вам нужны системные разрешения, хотя

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

Я нашел этот обходной путь для 17+, если вы хотите отключить интернет, это будет работать.

разрешение

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

метод

@SuppressWarnings({ "unchecked", "rawtypes" })
private void setMobileDataEnabled(boolean state) {
    try {
        final ConnectivityManager conman = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        final Class conmanClass = Class.forName(conman.getClass().getName());
        final Field iConnectivityManagerField = conmanClass.getDeclaredField("mService");
        iConnectivityManagerField.setAccessible(true);
        final Object iConnectivityManager = iConnectivityManagerField.get(conman);
        final Class iConnectivityManagerClass = Class.forName(iConnectivityManager.getClass().getName());
        final Method setMobileDataEnabledMethod = iConnectivityManagerClass.getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE);
        setMobileDataEnabledMethod.setAccessible(true);
        setMobileDataEnabledMethod.invoke(iConnectivityManager, state);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Другие вопросы по тегам