Como detectar o modo avião no Android?

92

Tenho um código em meu aplicativo que detecta se o Wi-Fi está conectado ativamente. Esse código aciona uma RuntimeException se o modo avião estiver habilitado. Eu gostaria de exibir uma mensagem de erro separada quando estiver neste modo de qualquer maneira. Como posso detectar com segurança se um dispositivo Android está no modo avião?

Sean W.
fonte
Dependendo de como você faz suas verificações, é bom estar ciente de que é possível ter o modo avião e o Wi-Fi habilitados ao mesmo tempo: heresthethingblog.com/2013/08/28/…
nibarius

Respostas:

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;

}
Alex Volovoy
fonte
33
No Jelly Bean 4.2, essa configuração mudou para Settings.Global.
Chris Feist
1
Isso gerou resultados indeterminados quando o chamei em resposta à intenção android.intent.action.AIRPLANE_MODE, uma vez que a mudança de modo leva tempo para ser concluída. Verifique Intent.ACTION_AIRPLANE_MODE_CHANGEDse você deseja fazer isso.
Noumenon
7
Apenas uma dica
:!
é o mesmo que dados de rede habilitados? Se não - há outro status de configuração para saber se os dados foram ativados pelo usuário?
ransh
o compilador diz que AIRPLANE_MODE_ON está obsoleto
Jean Raymond Daher
96

Ao estender a resposta de Alex para incluir a verificação de versão do SDK, temos:

/**
 * 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;
    }       
}
Tiago
fonte
5
O Eclipse não compilará isso a menos que você inclua @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)antes do método.
Noumenon,
1
Não consigo fazer isso funcionar no Intellij. Eu forneço a 2.2, então tenho minSdk = 8 e, portanto, tenho o "Android 2.2" como um SDK do projeto ". Isso, no entanto, significa que o código" Settings.Global "está vermelho e não compilará. Não quero definir 4.2 como SDK do projeto, pois posso perder algo não disponível no 2.2 ... isso me deixa louco, qual é a prática recomendada aqui? Alguma ideia?
Mathias
1
Altere seu SDK de destino
Louis CAD
53

E se você não quiser pesquisar se o modo avião está ativo ou não, você pode registrar um BroadcastReceiver para o intent SERVICE_STATE e reagir a ele.

Em seu ApplicationManifest (pré-Android 8.0):

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

ou programaticamente (todas as versões do 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);

E, conforme descrito nas outras soluções, você pode consultar o modo avião quando seu receptor foi notificado e lançar sua exceção.

saxos
fonte
2
observação: como há outras notificações SERVICE_STATE, você terá que verificar e armazenar o estado do modo avião antes de receber a notificação SERVICE_STATE e, em seguida, verificar o estado ao receber a notificação de estado do serviço e, em seguida, comparar os dois - para saber se o modo avião realmente mudou.
Mattorb
11
mpstx: ou use: IntentFilter intentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);/<action android:name="android.intent.action.AIRPLANE_MODE" />
Fralda de
3
Para esta solução, você precisará da permissão: <uses-permission android: name = "android.permission.READ_PHONE_STATE" />
Thomas Dignan
4
Use Intent.ACTION_AIRPLANE_MODE_CHANGED
Jeyanth Kumar,
4
Além disso, para saber se o modo de avião está ativado ou desativado, podemos usar o valor booleano extra na intenção que recebemos. boolean isPlaneModeOn = intent.getBooleanExtra("state", false); O booleano isPlaneModeOnserá truese o usuário ligou o modo avião ou falsese ele está desligado
Sudara
20

Ao registrar o Modo Avião BroadcastReceiver(resposta @saxos), acho que faz muito sentido obter o estado da configuração do Modo Avião imediatamente a Intent Extrasfim de evitar chamadas Settings.Globalou 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
fonte
3
Esta é a maneira mais eficiente de recuperar o estado real do modo avião. Isso deve gerar votos e ser a nova resposta aceita. +1 para ler os documentos que falam sobre este extra de intenção de "estado". Eu testei e funciona corretamente.
Louis CAD
7

A partir daqui :

 public static boolean isAirplaneModeOn(Context context){
   return Settings.System.getInt(
               context.getContentResolver(),
               Settings.System.AIRPLANE_MODE_ON, 
               0) != 0;
 }
Preet Sangha
fonte
"Settings.System.AIRPLANE_MODE_ON" é o mesmo que dados de rede habilitados? Se não - há outro status de configuração para saber se os dados foram ativados pelo usuário? -
ransh
5

a fim de se livrar da reclamação de depreciação (ao direcionar o API17 + e não se importar muito com a compatibilidade com versões anteriores), é necessário comparar com 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);
}

ao considerar API inferior:

/** 
 * @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
fonte
1
Settings.Global.AIRPLANE_MODE_ON Isso só funcionará para API 17+, fyi
Joseph Casey
1
adicionou compatibilidade com versões anteriores - embora seja quase igual ao exemplo acima agora.
Martin Zeitler
"Settings.System.AIRPLANE_MODE_ON" é o mesmo que dados de rede habilitados? Se não - há outro status de configuração para saber se os dados foram ativados pelo usuário?
ransh
2

No Oreo, não use o modo de avião broadCastReceiver. é uma intenção implícita. foi removido. Aqui está a lista de exceções atual . não está na lista no momento, portanto, não receberá dados. Considere-o morto.

conforme declarado por outro usuário acima, use o seguinte código:

 @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
fonte
1

Receptor de transmissão estática

Código de manifesto:

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

Código Java: arquivo Java do Broadcast Receiver

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

OU

Receptor de transmissão dinâmica

Código Java: arquivo java de atividade

Registre o receptor de transmissão no aplicativo aberto sem necessidade de adicionar o código no manifesto se você realizar uma ação apenas quando sua atividade for aberta, como verificar o modo avião, estiver ativado ou desativado ao acessar a 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);
}

Código Java: arquivo Java do Broadcast Receiver

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();
}
Tecnologias AXN Unicode
fonte
1

Do nível de 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;

    }
Vineesh TP
fonte
0

Escrevi esta aula que pode ser útil. Ele não retorna diretamente um booleano para informar se o Modo Avião está habilitado ou desabilitado, mas irá notificá-lo quando o Modo Avião for alterado de um para o outro.

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

}

Uso

// 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.
fonte
0

Aqui está a única coisa que funcionou para mim (API 27):

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

Onde brestá seu BroadcastReceiver. Eu acredito que com as recentes mudanças na permissão agora ambos ConnectivityManager.CONNECTIVITY_ACTIONe Intent.ACTION_AIRPLANE_MODE_CHANGEDsão necessários.

Gus
fonte
0

Desde o Jelly Bean (código de compilação 17), este campo foi movido para as configurações globais. Assim, para obter a melhor compatibilidade e robustez temos que cuidar de ambos os casos. O exemplo a seguir foi escrito em 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
}

Nota: Se você não mantiver o suporte para versões anteriores ao Jelly Bean, poderá omitir a cláusula if.
O valor que você obtém ao fazer referência Settings.System.AIRPLANE_MODE_ONé o mesmo que você encontra em Global. *

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

Esta é a versão do código anterior do Jelly Bean.

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

Você pode verificar se a internet está ligada

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
fonte
O problema com o método acima é que não leva em consideração as situações em que outros aplicativos modificam a conectividade. Exemplo se um usuário alterna o modo avião, mas outro aplicativo com os privilégios adequados ativa um rádio. Além disso, vamos supor que o rádio esteja ligado, mas não haja conexão ... de qualquer forma, a resposta acima realmente não nos diz se o modo avião está especificamente ligado ou desligado, apenas se o dispositivo tem uma conexão. Duas coisas diferentes.
logray