เราจะตรวจจับโหมดเครื่องบินบน Android ได้อย่างไร?


93

ฉันมีรหัสในแอปพลิเคชันที่ตรวจพบว่ามีการเชื่อมต่อ Wi-Fi อยู่หรือไม่ รหัสนั้นทริกเกอร์ RuntimeException หากเปิดใช้งานโหมดเครื่องบิน ฉันต้องการแสดงข้อความแสดงข้อผิดพลาดแยกต่างหากเมื่ออยู่ในโหมดนี้ ฉันจะตรวจสอบได้อย่างไรว่าอุปกรณ์ Android อยู่ในโหมดเครื่องบิน


ขึ้นอยู่กับวิธีการตรวจสอบของคุณคุณควรทราบว่าเป็นไปได้ที่จะเปิดใช้งานทั้งโหมดเครื่องบินและ Wi-Fi ในเวลาเดียวกัน: heresthethingblog.com/2013/08/28/…
nibarius

คำตอบ:


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
ใน Jelly Bean 4.2 Settings.Globalการตั้งค่านี้ได้ย้ายไป
Chris Feist

1
สิ่งนี้ให้ผลลัพธ์ที่ไม่แน่นอนเมื่อฉันเรียกมันตามความตั้งใจandroid.intent.action.AIRPLANE_MODEเนื่องจากการเปลี่ยนโหมดต้องใช้เวลานานกว่าจะเสร็จสมบูรณ์ ตรวจสอบIntent.ACTION_AIRPLANE_MODE_CHANGEDว่าคุณต้องการทำเช่นนั้นหรือไม่
Noumenon

7
เพียงคำใบ้:! = 0 ส่งคืนเท็จ (ปิดโหมดเครื่องบิน) และ == 0 ส่งคืนจริง (โหมดเครื่องบินเปิดอยู่)
jfmg

เหมือนกับข้อมูลเครือข่ายที่เปิดใช้งานหรือไม่ ถ้าไม่มี - มีสถานะการตั้งค่าอื่น ๆ ที่จะทราบว่าผู้ใช้เปิดใช้งานข้อมูลหรือไม่
เรียกค่าไถ่

คอมไพเลอร์แจ้งว่า 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

1
เปลี่ยนเป้าหมายของคุณ SDK
Louis CAD

54

และหากคุณไม่ต้องการสำรวจความคิดเห็นว่าโหมดเครื่องบินทำงานอยู่หรือไม่คุณสามารถลงทะเบียน BroadcastReceiver สำหรับ SERVICE_STATE Intent และตอบสนองได้

อย่างใดอย่างหนึ่งใน 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

11
mpstx: หรือใช้: IntentFilter intentFilter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);/<action android:name="android.intent.action.AIRPLANE_MODE" />
Nappy

3
สำหรับโซลูชันนี้คุณจะต้องได้รับอนุญาต: <ใช้ - อนุญาต android: name = "android.permission.READ_PHONE_STATE" />
Thomas Dignan

4
ใช้ Intent ACTION_AIRPLANE_MODE_CHANGED
Jeyanth Kumar

4
นอกจากนี้หากต้องการเปิดหรือปิดโหมดเครื่องบินทางอากาศเราสามารถใช้ค่าบูลีนพิเศษตามเจตนาที่เราได้รับ boolean isPlaneModeOn = intent.getBooleanExtra("state", false); บูลีนisPlaneModeOnจะเป็นtrueถ้าผู้ใช้เปิดโหมดเครื่องบินหรือfalseปิด
Sudara

20

เมื่อลงทะเบียนโหมดเครื่องบินBroadcastReceiver(คำตอบ @saxos) ฉันคิดว่ามันสมเหตุสมผลมากที่จะได้รับสถานะของการตั้งค่าโหมดเครื่องบินทันทีIntent Extrasเพื่อหลีกเลี่ยงการโทรSettings.Globalหรือ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
นี่เป็นวิธีที่มีประสิทธิภาพที่สุดในการดึงสถานะโหมดเครื่องบินจริง สิ่งนี้ควรได้รับการโหวตและเป็นคำตอบใหม่ที่ได้รับการยอมรับ +1 สำหรับการอ่านเอกสารที่พูดถึงเจตนาพิเศษของ "รัฐ" นี้ ฉันทดสอบแล้วและทำงานได้ดี
Louis CAD

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" เหมือนกับที่เปิดใช้งานข้อมูลเครือข่ายหรือไม่ ถ้าไม่มี - มีสถานะการตั้งค่าอื่น ๆ ที่จะทราบว่าผู้ใช้เปิดใช้งานข้อมูลหรือไม่ -
เรียกค่าไถ่


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+, fyi
Joseph Casey

1
เพิ่มความเข้ากันได้แบบย้อนกลับ - ในขณะที่เกือบจะเหมือนกับตัวอย่างข้างต้นในขณะนี้
Martin Zeitler

"Settings.System.AIRPLANE_MODE_ON" เหมือนกับที่เปิดใช้งานข้อมูลเครือข่ายหรือไม่ ถ้าไม่มี - มีสถานะการตั้งค่าอื่น ๆ ที่จะทราบว่าผู้ใช้เปิดใช้งานข้อมูลหรือไม่
เรียกค่าไถ่

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

เครื่องรับสัญญาณออกอากาศแบบคงที่

รหัส Manifest:

<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: ไฟล์จาวา 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();
}

หรือ

เครื่องรับสัญญาณออกอากาศแบบไดนามิก

รหัส 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: ไฟล์จาวา 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();
}

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

brBroadcastReceiver ของคุณอยู่ที่ไหน ฉันเชื่อว่าด้วยการเปลี่ยนแปลงล่าสุดในการอนุญาตในขณะนี้ConnectivityManager.CONNECTIVITY_ACTIONและIntent.ACTION_AIRPLANE_MODE_CHANGEDจำเป็น


0

ตั้งแต่ Jelly Bean (Build Code 17) ฟิลด์นี้ถูกย้ายไปที่ Global settings ดังนั้นเพื่อให้ได้ความเข้ากันได้ดีที่สุดและมีประสิทธิภาพเราต้องดูแลทั้งสองกรณี ตัวอย่างต่อไปนี้เขียนใน 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 clause ได้
มูลค่าที่คุณได้รับในขณะอ้างอิง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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.