如何在Android上检测飞行模式?


92

我的应用程序中有用于检测Wi-Fi是否已主动连接的代码。如果启用飞行模式,则该代码将触发RuntimeException。无论如何,我想在此模式下显示单独的错误消息。如何可靠地检测Android设备是否处于飞行模式?


视您的检查方式而定,很高兴知道可以同时启用飞行模式和Wi-Fi:heresthethingblog.com/2013/08/28/…–
nibarius

Answers:


137
/**
* 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
当我响应intent调用它时,传递的结果不确定android.intent.action.AIRPLANE_MODE,因为模式更改需要时间才能完成。检查Intent.ACTION_AIRPLANE_MODE_CHANGED是否要这样做。
Noumenon

7
只是一个提示:!= 0返回false(飞机模式关闭),== 0返回true(飞机模式打开)
jfmg

是否与启用网络数据相同?如果不是-是否还有其他设置状态可以知道用户是否启用了数据?
ransh

编译器说AIRPLANE_MODE_ON已弃用
Jean Raymond Daher

96

通过扩展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
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中无法提供的功能...这让我发疯,这是什么最佳实践?您知道吗?
Mathias 2014年

1
更改您的targetSDK
路易CAD

53

并且,如果您不想轮询“飞行模式”是否处于活动状态,则可以为SERVICE_STATE Intent注册一个BroadcastReceiver并对其作出反应。

在您的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 2011年

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 2011年

4
Use Intent.ACTION_AIRPLANE_MODE_CHANGED
Jeyanth Kumar

4
另外,要了解是否启用或禁用飞行模式,我们可以在收到的意图中使用布尔值布尔值。boolean isPlaneModeOn = intent.getBooleanExtra("state", false); 布尔isPlaneModeOntrue用户是否已接通的平面模式或者false如果它被关闭
Sudara

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
    }
}

3
这是检索实际飞行模式状态的最有效方法。这应该获得投票,并且是新接受的答案。+1用于阅读额外讨论此“状态”意图的文档。我进行了测试,它可以正常工作。
路易CAD


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
增加了向后兼容性-尽管它与上面的示例几乎相同。
马丁·泽特勒

“ 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;
        }
    }

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

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)以来,此字段已移至“全局”设置。因此,为了获得最佳的兼容性和鲁棒性,我们必须同时考虑这两种情况。以下示例是用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
}

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

}


上述方法的问题在于,它没有考虑其他应用程序修改连接的情况。例如,如果用户打开飞行模式,但随后另一个具有适当特权的应用启用了收音机。再进一步,假设无线电已打开,但随后没有连接...无论如何,以上答案实际上并没有告诉我们是否专门打开或关闭飞行模式,即使设备已连接也是如此。两件事。
logray 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.