Jak można wykryć tryb samolotowy na Androidzie?


93

Mam w aplikacji kod, który wykrywa aktywne połączenie Wi-Fi. Ten kod wyzwala wyjątek RuntimeException, jeśli włączony jest tryb samolotowy. Chciałbym mimo wszystko wyświetlić oddzielny komunikat o błędzie w tym trybie. Jak mogę niezawodnie wykryć, czy urządzenie z Androidem działa w trybie samolotowym?


W zależności od tego, jak przeprowadzasz kontrole, dobrze jest mieć świadomość, że możliwe jest jednoczesne włączenie trybu samolotowego i Wi-Fi: heresthethingblog.com/2013/08/28/…
nibarius

Odpowiedzi:


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
W Jelly Bean 4.2 to ustawienie zostało przeniesione do Settings.Global.
Chris Feist

1
Dało to nieokreślone wyniki, gdy wywołałem je w odpowiedzi na zamiar android.intent.action.AIRPLANE_MODE, ponieważ zmiana trybu wymaga czasu. Sprawdź, Intent.ACTION_AIRPLANE_MODE_CHANGEDjeśli chcesz to zrobić.
Noumenon

7
Tylko wskazówka
:!

czy to to samo, co włączone dane sieciowe? Jeśli nie - czy istnieje inny stan ustawień, aby wiedzieć, czy dane zostały włączone przez użytkownika?
ransh

kompilator mówi, że AIRPLANE_MODE_ON jest przestarzały
Jean Raymond Daher

96

Rozszerzając odpowiedź Alexa o sprawdzenie wersji SDK, otrzymaliśmy:

/**
 * 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 nie skompiluje tego, chyba że dodasz @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)przed metodą.
Noumenon

1
Nie mogę tego zrobić w Intellij. Obsługuję 2.2, więc mam minSdk = 8 i dlatego mam "Android 2.2" jako Project SDK ". Oznacza to jednak, że kod" Settings.Global "jest czerwony i nie można go skompilować. Nie ' t chcesz ustawić jako SDK 4.2 projektu odkąd może przegapić coś nie dostępne w 2.2 ... to doprowadza mnie do szału, co jest najlepsze praktyki tutaj Każdy pomysł?
Mathias

1
Zmień celSDK
Louis CAD

54

A jeśli nie chcesz sondować, czy tryb samolotowy jest aktywny, czy nie, możesz zarejestrować odbiornik BroadcastReceiver dla intencji SERVICE_STATE i zareagować na to.

Albo w pliku ApplicationManifest (przed Androidem 8.0):

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

lub programowo (wszystkie wersje Androida):

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

I jak opisano w innych rozwiązaniach, możesz odpytać tryb samolotowy, gdy twój odbiornik został powiadomiony i zgłosić wyjątek.


2
uwaga: ponieważ istnieją inne powiadomienia SERVICE_STATE, będziesz musiał sprawdzić i zapisać stan trybu samolotowego przed otrzymaniem powiadomienia SERVICE_STATE, a następnie sprawdzić jego stan po otrzymaniu powiadomienia o stanie usługi, a następnie porównać dwa - aby wiedzieć czy tryb samolotowy faktycznie się zmienił.
mattorb

11
mpstx: lub użyj: IntentFilter intentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);/<action android:name="android.intent.action.AIRPLANE_MODE" />
Nappy

3
W przypadku tego rozwiązania będziesz potrzebować pozwolenia: <używa-pozwolenia android: name = "android.permission.READ_PHONE_STATE" />
Thomas Dignan,

4
Użyj Intent.ACTION_AIRPLANE_MODE_CHANGED
Jeyanth Kumar

4
Aby sprawdzić, czy tryb samolotu jest włączony, czy wyłączony, możemy użyć dodatkowej wartości logicznej w otrzymanym celu. boolean isPlaneModeOn = intent.getBooleanExtra("state", false); Wartość logiczna isPlaneModeOnbędzie, truejeśli użytkownik włączył tryb samolotowy lub falsejeśli jest wyłączony
Sudara

20

Podczas rejestracji trybu samolotowego BroadcastReceiver(odpowiedź @saxos) wydaje mi się, że bardzo sensowne jest uzyskanie stanu ustawienia trybu samolotowego od razu Intent Extras, aby uniknąć dzwonienia Settings.Globallub 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
Jest to najbardziej efektywny sposób pobierania aktualnego stanu trybu samolotowego. Powinno to zwiększyć liczbę głosów i być nową zaakceptowaną odpowiedzią. +1 za przeczytanie dokumentów, które mówią o tym „stanie” intencji dodatkowo. Przetestowałem i działa poprawnie.
Louis CAD

7

Od tutaj :

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

Czy „Settings.System.AIRPLANE_MODE_ON” to to samo, co włączone dane sieciowe? Jeśli nie - czy istnieje inny stan ustawień, aby wiedzieć, czy dane zostały włączone przez użytkownika? -
ransh


5

aby pozbyć się reklamacji amortyzacji (celując w API17 + i nie przejmując się zbytnio kompatybilnością wsteczną), należy porównać z 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);
}

rozważając niższe 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 To będzie działać tylko dla API 17+, fyi
Joseph Casey

1
dodano kompatybilność wsteczną - podczas gdy teraz jest prawie taka sama jak w przykładzie powyżej.
Martin Zeitler,

Czy „Settings.System.AIRPLANE_MODE_ON” to to samo, co włączone dane sieciowe? Jeśli nie - czy istnieje inny stan ustawień, aby wiedzieć, czy dane zostały włączone przez użytkownika?
ransh

2

W Oreo nie używaj broadCastReceiver w trybie samolotowym. jest to ukryta intencja. został usunięty. Oto aktualna lista wyjątków . nie ma go obecnie na liście, więc nie powinien odebrać danych. Uważaj to za martwe.

jak stwierdził inny użytkownik powyżej, użyj następującego kodu:

 @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

Statyczny odbiornik transmisji

Kod manifestu:

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

Kod Java: plik java odbiornika transmisji

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

LUB

Dynamiczny odbiornik transmisji

Kod Java: plik Java aktywności

Zarejestruj odbiornik transmisji przy otwartej aplikacji nie ma potrzeby dodawania kodu w manifeście, jeśli wykonujesz akcję tylko wtedy, gdy Twoja aktywność jest otwarta, np. Sprawdź, czy tryb samolotowy jest włączony lub wyłączony, kiedy uzyskujesz dostęp do Internetu itp.

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

Kod Java: plik java odbiornika transmisji

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

Od poziomu 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

Napisałem te zajęcia, które mogą być pomocne. Nie zwraca bezpośrednio wartości logicznej, aby powiedzieć, czy tryb samolotowy jest włączony, czy wyłączony, ale powiadomi Cię, gdy tryb samolotowy zostanie zmieniony z jednego na drugi.

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

}

Stosowanie

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

Oto jedyna rzecz, która zadziałała dla mnie (API 27):

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

Gdzie brjest twój BroadcastReceiver. Uważam, że w związku z ostatnimi zmianami w pozwoleniach teraz zarówno ConnectivityManager.CONNECTIVITY_ACTIONi jak Intent.ACTION_AIRPLANE_MODE_CHANGEDsą potrzebne.


0

Od czasu Jelly Bean (kod kompilacji 17) to pole zostało przeniesione do ustawień globalnych. Dlatego, aby uzyskać najlepszą kompatybilność i solidność, musimy zadbać o oba przypadki. Poniższy przykład jest napisany w Kotlinie.

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
}

Uwaga: jeśli nie utrzymujesz wsparcia dla wersji starszych niż Jelly Bean, możesz pominąć klauzulę if.
Wartość, którą otrzymujesz podczas tworzenia odniesień Settings.System.AIRPLANE_MODE_ON, jest taka sama, jak ta, którą znajdziesz w sekcji Global. *

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

To jest powyższa wersja poprzedniego kodu z galaretką.

fun isInAirplane(context: Context): Boolean {
    return Settings.Global.getInt(
        context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0
    ) != 0
}

-4

Możesz sprawdzić, czy internet jest włączony

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

}


Problem z powyższą metodą polega na tym, że nie uwzględnia ona sytuacji, w których inne aplikacje modyfikują łączność. Przykład, jeśli użytkownik włączy tryb samolotowy, ale inna aplikacja z odpowiednimi uprawnieniami włączy radio. I dalej, załóżmy, że radio jest włączone, ale wtedy nie ma połączenia ... w każdym razie powyższa odpowiedź naprawdę nie mówi nam, czy tryb samolotowy jest włączony, czy wyłączony, tylko czy urządzenie ma połączenie. Dwie różne rzeczy.
logray
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.