如何在安卓手机上检测飞行模式?

101

我在我的应用程序中有一段代码,可以检测Wi-Fi是否处于活动连接状态。如果飞行模式已启用,则该代码会触发RuntimeException异常。无论如何,我希望在此模式下显示一个单独的错误消息。如何可靠地检测Android设备是否处于飞行模式?


根据您进行检查的方式,需要注意的是可能同时启用飞行模式和Wi-Fi:https://heresthethingblog.com/2013/08/28/android-iphone-tip-turn-airplane/ - nibarius
13个回答

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

}

35
在Jelly Bean 4.2中,此设置已移至“Settings.Global”。 - Chris Feist
1
当我以回应意图android.intent.action.AIRPLANE_MODE的方式调用它时,它会产生不确定的结果,因为模式更改需要时间才能完成。如果您想这样做,请检查Intent.ACTION_AIRPLANE_MODE_CHANGED - Noumenon
7
提示:!= 0 返回 false(飞行模式关闭),== 0 返回 true(飞行模式开启)。 - jfmg
它是否与网络数据启用相同?如果不是,是否有其他设置状态可知道用户是否启用了数据? - ransh
编译器说 AIRPLANE_MODE_ON 已过时。 - Jean Raymond Daher

100

通过扩展Alex的回答以包括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
除非你在方法之前添加@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1),否则Eclipse无法编译这个。 - Noumenon
1
我无法在Intellij中使其工作。 我针对2.2进行了优化,因此我将minSdk设置为8,因此将“Android 2.2”设置为项目SDK。 然而,这意味着“Settings.Global”代码为红色并且无法编译。 我不想将4.2设置为项目SDK,因为我可能会错过2.2中不存在的某些内容... 这让我疯了,这里有什么最佳实践吗? 任何想法? - Mathias
1
改变你的targetSDK。 - Louis CAD

55

如果你不想轮询Airplane Mode是否开启,那么你可以注册一个接收器来监听SERVICE_STATE意图并作出反应。

在你的中进行注册(适用于 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
12
你可以使用以下代码来检测飞行模式的状态变化: 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
5
使用 Intent.ACTION_AIRPLANE_MODE_CHANGED。 - Jeyanth Kumar
6
另外,要获取飞行模式是否已打开或关闭,我们可以使用接收到的意图中的布尔附加值。boolean isPlaneModeOn = intent.getBooleanExtra("state", false); 如果用户已经打开了飞行模式,则布尔值 isPlaneModeOn 将为 true,如果它被关闭,则为 false - Sudara
显示剩余2条评论

20

在注册飞行模式BroadcastReceiver(@saxos的回答)时,我认为立即从Intent Extras获取飞行模式设置状态非常有意义,以避免调用Settings.GlobalSettings.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
    }
}

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
请问如何在连接移动网络的情况下判断移动数据是否启用或禁用?@ransh - Preet Sangha

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+,供参考。 - Joseph Casey
1
增加了向后兼容性——尽管现在它几乎与上面的示例相同。 - Martin Zeitler
“Settings.System.AIRPLANE_MODE_ON” 是否等同于网络数据已启用?如果不是,是否有其他设置状态可以知道用户是否启用了数据? - ransh

3
在Oreo中,请不要使用飞行模式广播接收器,它是一个隐式意图。已经被移除。这是当前的异常列表。它目前不在列表中,因此应该无法接收数据。考虑它已经废弃。
如另一个用户所述,请使用以下代码:
 @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;
        }
    }

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

OR

动态广播接收器

Java代码:活动java文件

当应用程序打开时注册广播接收器,如果您只在打开活动时执行某个操作,例如在访问Internet时检查飞行模式是否打开或关闭等,则无需在清单中添加代码。

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

1
自从果冻豆(Build Code 17)以来,此字段已移至全局设置。因此,为了实现最佳兼容性和稳健性,我们必须同时考虑两种情况。以下示例是用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
}

注意:如果您不支持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
}

1

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

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接