Как определить режим полета на Android?

93

В моем приложении есть код, который определяет, активно ли подключен Wi-Fi. Этот код вызывает исключение RuntimeException, если включен режим полета. В любом случае я хотел бы отображать отдельное сообщение об ошибке в этом режиме. Как я могу надежно определить, находится ли устройство Android в режиме полета?

Шон В.
источник
В зависимости от того, как вы проводите свои проверки, полезно знать, что можно одновременно включить режим полета и Wi-Fi: heresthethingblog.com/2013/08/28/…
nibarius

Ответы:

138
/**
* Gets the state of Airplane Mode.
* 
* @param context
* @return true if enabled.
*/
private static boolean isAirplaneModeOn(Context context) {

   return Settings.System.getInt(context.getContentResolver(),
           Settings.Global.AIRPLANE_MODE_ON, 0) != 0;

}
Алексей Воловой
источник
33
В Jelly Bean 4.2 этот параметр переместился на Settings.Global.
Крис Фейст
1
Это дало неопределенные результаты, когда я вызвал его в ответ на намерение android.intent.action.AIRPLANE_MODE, так как изменение режима требует времени для завершения. Проверьте против, Intent.ACTION_AIRPLANE_MODE_CHANGEDесли хотите это сделать.
Noumenon
7
Просто подсказка:! = 0 возвращает false (режим полета выключен), а == 0 возвращает true (режим
полета включен
это то же самое, что и сетевые данные? Если нет - есть ли другой статус настроек, чтобы узнать, были ли данные включены пользователем?
ransh
компилятор говорит, что AIRPLANE_MODE_ON устарел
Жан Реймонд Дахер
96

Расширяя ответ Алекса, включив в него проверку версии SDK, мы получаем:

/**
 * Gets the state of Airplane Mode.
 * 
 * @param context
 * @return true if enabled.
 */
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
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;
    }       
}
Тьяго
источник
5
Eclipse не скомпилирует это, если вы не добавите его @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)перед методом.
Noumenon
1
Я не могу сделать это в Intellij. Я использую 2.2, поэтому у меня minSdk = 8, и поэтому у меня есть "Android 2.2" как Project SDK ". Однако это означает, что код" Settings.Global "красный и не компилируется. Я не Я не хочу установить 4.2 в качестве SDK проекта, так как я могу пропустить что-то, недоступное в 2.2 ... это сводит меня с ума, что здесь лучше всего? Любая идея?
Матиас
1
Change your targetSDK
Louis CAD
54

И если вы не хотите опрашивать, активен ли режим полета или нет, вы можете зарегистрировать BroadcastReceiver для намерения SERVICE_STATE и отреагировать на него.

Либо в вашем ApplicationManifest (до Android 8.0):

<receiver android:enabled="true" android:name=".ConnectivityReceiver">
    <intent-filter>
        <action android:name="android.intent.action.AIRPLANE_MODE"/>
    </intent-filter>
</receiver>

или программно (все версии Android):

IntentFilter intentFilter = new IntentFilter("android.intent.action.AIRPLANE_MODE");

BroadcastReceiver receiver = new BroadcastReceiver() {
      @Override
      public void onReceive(Context context, Intent intent) {
            Log.d("AirplaneMode", "Service state changed");
      }
};

context.registerReceiver(receiver, intentFilter);

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

саксофоны
источник
2
примечание: поскольку есть другие уведомления SERVICE_STATE, вам нужно будет проверить и сохранить состояние режима полета до получения уведомления SERVICE_STATE, а затем проверить его состояние при получении уведомления о состоянии службы, а затем сравнить два - чтобы знать если режим полета действительно изменился.
mattorb
11
mpstx: или используйте: IntentFilter intentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);/<action android:name="android.intent.action.AIRPLANE_MODE" />
Nappy
3
Для этого решения вам потребуется разрешение: <uses-permission android: name = "android.permission.READ_PHONE_STATE" />
Thomas Dignan
4
Используйте Intent.ACTION_AIRPLANE_MODE_CHANGED
Джеянт Кумар,
4
Также, чтобы узнать, включен или выключен режим полета, мы можем использовать логическое дополнительное значение в полученном намерении. boolean isPlaneModeOn = intent.getBooleanExtra("state", false); Логическое значение isPlaneModeOnбудет, trueесли пользователь включил режим самолета или falseесли он выключен
Судара
20

При регистрации режима BroadcastReceiverполета (ответ @saxos) я думаю, что имеет смысл сразу же получить состояние настройки режима полета из Intent Extras, чтобы избежать звонков Settings.Globalили Settings.System:

@Override
public void onReceive(Context context, Intent intent) {

    boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
    if(isAirplaneModeOn){

       // handle Airplane Mode on
    } else {
       // handle Airplane Mode off
    }
}
Элджон
источник
3
Это наиболее эффективный способ получить фактическое состояние режима полета. Это должно набрать голоса и стать новым принятым ответом. +1 за чтение документов, в которых говорится об этом "государственном" намерении. Я протестировал, и он работает нормально.
Луи CAD
7

От сюда :

 public static boolean isAirplaneModeOn(Context context){
   return Settings.System.getInt(
               context.getContentResolver(),
               Settings.System.AIRPLANE_MODE_ON, 
               0) != 0;
 }
Прит Сангха
источник
Включено ли "Settings.System.AIRPLANE_MODE_ON" то же самое, что и сетевые данные? Если нет - есть ли другой статус настроек, чтобы узнать, были ли данные включены пользователем? -
ransh
5

Чтобы избавиться от претензии по износу (при ориентации на API17 + и не слишком заботясь об обратной совместимости), нужно сравнить с Settings.Global.AIRPLANE_MODE_ON:

/** 
 * @param Context context
 * @return boolean
**/
private static boolean isAirplaneModeOn(Context context) {
   return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0);
}

при рассмотрении более низкого API:

/** 
 * @param Context context
 * @return boolean
**/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@SuppressWarnings({ "deprecation" })
private static boolean isAirplaneModeOn(Context context) {
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1){
        /* API 17 and above */
        return Settings.Global.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
    } else {
        /* below */
        return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0;
    }
}
Мартин Цайтлер
источник
1
Settings.Global.AIRPLANE_MODE_ON Это будет работать только для API 17+, fyi
Джозеф Кейси
1
добавлена ​​обратная совместимость - сейчас она почти такая же, как в примере выше.
Мартин Цайтлер
Включено ли "Settings.System.AIRPLANE_MODE_ON" то же самое, что и сетевые данные? Если нет - есть ли другой статус настроек, чтобы узнать, были ли данные включены пользователем?
ransh
2

В Oreo не используйте режим полета BroadCastReceiver. это неявное намерение. он был удален. Вот текущий список исключений . в настоящее время его нет в списке, поэтому он не должен получать данные. Считайте это мертвым.

как указано выше другим пользователем, используйте следующий код:

 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    @SuppressWarnings({ "deprecation" })
    public static boolean isAirplaneModeOn(Context context) {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1){
        /* API 17 and above */
            return Settings.Global.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
        } else {
        /* below */
            return Settings.System.getInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) != 0;
        }
    }
j2emanue
источник
1

Статический широковещательный приемник

Код манифеста:

<receiver android:name=".airplanemodecheck" android:enabled="true"
 android:exported="true">
  <intent-filter>
     <action android:name="android.intent.action.AIRPLANE_MODE"></action>
  </intent-filter>
</receiver>

Код Java: java-файл широковещательного приемника

if(Settings.System.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0)== 0)
{
  Toast.makeText(context, "AIRPLANE MODE Off", Toast.LENGTH_SHORT).show();
}
else
{
 Toast.makeText(context, "AIRPLANE MODE On", Toast.LENGTH_SHORT).show();
}

ИЛИ

Приемник динамического вещания

Код Java: файл активности java

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

airplanemodecheck reciver;

@Override
protected void onResume() {
   super.onResume();
   IntentFilter intentFilter = new IntentFilter();
   intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
   reciver = new airplanemodecheck();
   registerReceiver(reciver, intentFilter);
}

@Override
protected void onStop() {
  super.onStop();
  unregisterReceiver(reciver);
}

Код Java: java-файл широковещательного приемника

if(Settings.System.getInt(context.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0)== 0)
{
  Toast.makeText(context, "AIRPLANE MODE Off", Toast.LENGTH_SHORT).show();
}
else
{
 Toast.makeText(context, "AIRPLANE MODE On", Toast.LENGTH_SHORT).show();
}
Технологии AXN Unicode
источник
1

С уровня API - 17

/**
     * Gets the state of Airplane Mode.
     *
     * @param context
     * @return true if enabled.
     */
    private static boolean isAirplaneModeOn(Context context) {

        return Settings.Global.getInt(context.getContentResolver(),
                Settings.Global.AIRPLANE_MODE_ON, 0) != 0;

    }
Винеш ТП
источник
0

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

public abstract class AirplaneModeReceiver extends BroadcastReceiver {

    private Context context;

    /**
     * Initialize tihe reciever with a Context object.
     * @param context
     */
    public AirplaneModeReceiver(Context context) {
        this.context = context;
    }

    /**
     * Receiver for airplane mode status updates.
     *
     * @param context
     * @param intent
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        if(Settings.System.getInt(
                context.getContentResolver(),
                Settings.Global.AIRPLANE_MODE_ON, 0
        ) == 0) {
            airplaneModeChanged(false);
        } else {
            airplaneModeChanged(true);
        }
    }

    /**
     * Used to register the airplane mode reciever.
     */
    public void register() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        context.registerReceiver(this, intentFilter);
    }

    /**
     * Used to unregister the airplane mode reciever.
     */
    public void unregister() {
        context.unregisterReceiver(this);
    }

    /**
     * Called when airplane mode is changed.
     *
     * @param enabled
     */
    public abstract void airplaneModeChanged(boolean enabled);

}

Применение

// Create an AirplaneModeReceiver
AirplaneModeReceiver airplaneModeReceiver;

@Override
protected void onResume()
{
    super.onResume();

    // Initialize the AirplaneModeReceiver in your onResume function
    // passing it a context and overriding the callback function
    airplaneModeReceiver = new AirplaneModeReceiver(this) {
        @Override
        public void airplaneModeChanged(boolean enabled) {
            Log.i(
                "AirplaneModeReceiver",
                "Airplane mode changed to: " + 
                ((active) ? "ACTIVE" : "NOT ACTIVE")
            );
        }
    };

    // Register the AirplaneModeReceiver
    airplaneModeReceiver.register();
}

@Override
protected void onStop()
{
    super.onStop();

    // Unregister the AirplaneModeReceiver
    if (airplaneModeReceiver != null)
        airplaneModeReceiver.unregister();
}
Натан Ф.
источник
0

Вот единственное, что у меня сработало (API 27):

IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
this.registerReceiver(br, filter);

Где brваш BroadcastReceiver. Я считаю, что с недавними изменениями в разрешении сейчас и то, ConnectivityManager.CONNECTIVITY_ACTIONи другое Intent.ACTION_AIRPLANE_MODE_CHANGEDнеобходимы.

Гас
источник
0

Начиная с Jelly Bean (код сборки 17), это поле перемещено в глобальные настройки. Таким образом, для достижения наилучшей совместимости и надежности мы должны позаботиться о обоих случаях. Следующий пример написан на Котлине.

fun isInAirplane(context: Context): Boolean {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        Settings.Global.getInt(
            context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0
        )
    } else {
        Settings.System.getInt(
            context.contentResolver, Settings.System.AIRPLANE_MODE_ON, 0
        )
    } != 0
}

Примечание. Если вы не сохраняете поддержку версий до Jelly Bean, вы можете опустить предложение if.
Значение, которое вы получаете при ссылке Settings.System.AIRPLANE_MODE_ON, такое же, как и в Global. *

    /**
     * @deprecated Use {@link android.provider.Settings.Global#AIRPLANE_MODE_ON} instead
     */
    @Deprecated
    public static final String AIRPLANE_MODE_ON = Global.AIRPLANE_MODE_ON;

Это версия предыдущего кода в виде мармелада.

fun isInAirplane(context: Context): Boolean {
    return Settings.Global.getInt(
        context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0
    ) != 0
}
Андреа Чоккарелли
источник
-4

Вы можете проверить, включен ли интернет

public class ConnectionDetector {

private Context _context;

public ConnectionDetector(Context context){
    this._context = context;
}

public boolean isConnectingToInternet(){
    ConnectivityManager connectivity = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
      if (connectivity != null)
      {
          NetworkInfo[] info = connectivity.getAllNetworkInfo();
          if (info != null)
              for (int i = 0; i < info.length; i++)
                  if (info[i].getState() == NetworkInfo.State.CONNECTED)
                  {
                      return true;
                  }

      }
      return false;
}

}

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