95

I have code in my application that detects if Wi-Fi is actively connected. That code triggers a RuntimeException if airplane mode is enabled. I would like to display a separate error message when in this mode anyway. How can I reliably detect if an Android device is in airplane mode?

Tiago
  • 3,013
  • 1
  • 29
  • 45
Sean W.
  • 4,446
  • 6
  • 35
  • 61
  • Depending on how you do your checks, it's good to be aware that it's possible to have both airplane mode and Wi-Fi enabled at the same time: https://heresthethingblog.com/2013/08/28/android-iphone-tip-turn-airplane/ – nibarius Apr 09 '18 at 10:54

13 Answers13

141
/**
* 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;

}
zackygaurav
  • 3,941
  • 3
  • 23
  • 38
Alex Volovoy
  • 65,307
  • 13
  • 71
  • 53
  • 34
    In Jelly Bean 4.2, this setting has moved to `Settings.Global`. – Chris Feist Nov 28 '12 at 21:46
  • 1
    This delivered indeterminate results when I called it in response to the intent `android.intent.action.AIRPLANE_MODE`, since the mode change takes time to complete. Check against `Intent.ACTION_AIRPLANE_MODE_CHANGED` if you want to do that. – Noumenon Oct 30 '13 at 08:02
  • 7
    Just a hint: != 0 returns false (airplane mode is off) and == 0 returns true (airplane mode is on) – jfmg Aug 10 '15 at 14:05
  • is it the same as network data enabled ? If not - is there other settings status to know if data was enabled by user ? – ransh Jan 24 '17 at 12:57
  • compiler says AIRPLANE_MODE_ON is deprecated – Jean Raymond Daher Aug 03 '18 at 15:54
97

By extending Alex's answer to include SDK version checking we have:

/**
 * 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;
    }       
}
maksim
  • 794
  • 2
  • 8
  • 16
Tiago
  • 3,013
  • 1
  • 29
  • 45
  • 5
    Eclipse won't compile this unless you add `@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)` before the method. – Noumenon Oct 30 '13 at 07:59
  • 1
    I can't make this work in Intellij. I cater to 2.2, so i have minSdk=8, and therefor have the "Android 2.2" as a Project SDK". This, however, means that the "Settings.Global" code is red and won't compile. I don't want to set 4.2 as project SDK since i might miss something not available in 2.2... this drives me crazy, what is best practice here? Any idea? – Mathias Jul 03 '14 at 13:17
  • 1
    Change your targetSDK – Louis CAD Jul 01 '15 at 12:58
54

And if you don't want to poll if the Airplane Mode is active or not, you can register a BroadcastReceiver for the SERVICE_STATE Intent and react on it.

Either in your ApplicationManifest (pre-Android 8.0):

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

or programmatically (all Android versions):

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);

And as described in the other solutions, you can poll the airplane mode when your receiver was notified and throw your exception.

Lawrence Kesteloot
  • 3,786
  • 2
  • 28
  • 27
saxos
  • 2,427
  • 1
  • 18
  • 21
  • Interesting idea. I will keep that in mind if I decide that I need to check the status more than once. Thanks! – Sean W. Nov 30 '10 at 22:49
  • 2
    note: since there are other SERVICE_STATE notifications, you will have to check and store the state of airplane mode prior to receiving the SERVICE_STATE notification, and then check the state of it when receiving the service state notification, then compare the two -- to know if airplane mode actually changed. – mattorb Mar 29 '11 at 14:29
  • 11
    mpstx: or use: `IntentFilter intentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);` / `` – Nappy Apr 01 '11 at 12:19
  • 3
    For this solution you will need the permission: – Thomas Dignan Jun 30 '11 at 17:06
  • Last two comments was gold to me ;) – Warpzit Oct 31 '11 at 20:39
  • 4
    Use Intent.ACTION_AIRPLANE_MODE_CHANGED – Jeyanth Kumar Apr 19 '12 at 06:27
  • 4
    Also to get if the air plane mode is turned on or off, we can use the boolean extra value in the intent we received. `boolean isPlaneModeOn = intent.getBooleanExtra("state", false);` The boolean `isPlaneModeOn` will be `true` if the user has turned on the plane mode or `false` if it is turned off – Sudara Apr 03 '15 at 05:00
20

When registering the Airplane Mode BroadcastReceiver (@saxos answer) I think it makes a lot of sense to get the state of the Airplane Mode setting right away from the Intent Extras in order to avoid calling Settings.Global or 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
    }
}
eldjon
  • 2,674
  • 1
  • 16
  • 23
  • 3
    This is the most efficient way to retrieve the actual airplane mode state. This should get up votes and be the new accepted answer. +1 for reading the docs which talk about this "state" intent extra. I tested and it works properly. – Louis CAD Aug 25 '16 at 14:05
7

From here :

 public static boolean isAirplaneModeOn(Context context){
   return Settings.System.getInt(
               context.getContentResolver(),
               Settings.System.AIRPLANE_MODE_ON, 
               0) != 0;
 }
Preet Sangha
  • 61,126
  • 17
  • 134
  • 202
  • Is "Settings.System.AIRPLANE_MODE_ON" the same as network data enabled ? If not - is there other settings status to know if data was enabled by user ? – – ransh Jan 24 '17 at 12:57
  • http://stackoverflow.com/questions/12806709/how-to-tell-if-mobile-network-data-is-enabled-or-disabled-even-when-connected @ransh – Preet Sangha Jan 26 '17 at 09:35
5

in order to get rid of the the depreciation complaint (when targeting API17+ and not caring too much about the backward compatibility), one has to compare with 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);
}

when considering lower 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;
    }
}
Martin Zeitler
  • 49,224
  • 12
  • 97
  • 156
3

In Oreo please do not use the airplane mode broadCastReceiver. it is an implicit intent. it has been removed. Here is the current exceptions list. its not currently on the list so should fail to receive data. Consider it dead.

as stated by another user above use the following code:

 @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
  • 51,417
  • 46
  • 239
  • 380
1

Static Broadcast Receiver

Manifest code:

<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 code: Broadcast Receiver java file

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();
}

OR

Dynamic Broadcast Receiver

Java code: Activity java file

Register broadcast receiver on application open no need to add code in manifest if you take an action only when your activity open like check airplane mode is on or off when you access the internet etc

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 code: Broadcast Receiver java file

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();
}
1

From API Level - 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;

    }
Vineesh TP
  • 7,025
  • 9
  • 54
  • 102
0

I wrote this class that might be helpful. It doesn't directly return a boolean to tell you if Airplane Mode is enabled or disabled, but it will notify you when Airplane Mode is changed from one to the other.

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);

}

Usage

// 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();
}
Nathan F.
  • 2,575
  • 2
  • 23
  • 55
0

Here's the only thing what worked for me (API 27):

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

Where br is your BroadcastReceiver. I believe that with the recent changes in permission now both ConnectivityManager.CONNECTIVITY_ACTION and Intent.ACTION_AIRPLANE_MODE_CHANGEDare needed.

Gus
  • 13,381
  • 5
  • 22
  • 28
0

Since Jelly Bean (Build Code 17), this field has been moved to Global settings. Thus, to achieve the best compatibility and robustness we have to take care of both cases. The following example is written in Kotlin.

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
}

Note: If you do not keep support for versions before Jelly Bean, you can omit the if clause.
The value that you get while referencing Settings.System.AIRPLANE_MODE_ON, is the same as the one you find under Global.*

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

This is the above-jelly bean version of the previous code.

fun isInAirplane(context: Context): Boolean {
    return Settings.Global.getInt(
        context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0
    ) != 0
}
Andrea
  • 573
  • 5
  • 18
-4

You could check if the internet is on

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
  • 643
  • 2
  • 14
  • 16
  • The problem with the above method is that is does not take into account situations where other apps modify connectivity. Example if a user switches airplane mode on, but then another app with the proper privileges enables a radio. And further, lets suppose the radio is on but then there is no connection... anyhow the above answer really doesn't tell us if airplane mode specifically is on or off, just if the device has a connection. Two different things. – logray Dec 06 '12 at 19:52