ภาพรวม
ตัวอย่างนี้สาธิตวิงการใช้ BroadcastReceiver เพื่อฟัง Event Intent.ACTION_AIRPLANE_MODE_CHANGED ซึ่งจะ Trigger ทุกครั้งที่ผู้ใช้เปิด/ปิดโหมดเครื่องบิน
ขั้นตอนการสร้างโปรเจกต์
ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่
Android Studio → File → New Project → Empty Activity
ขั้นตอนที่ 2: Layout (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="30sp"
android:gravity="center"
android:padding="16dp"
android:text="รอการเปลี่ยนแปลง Airplane Mode..." />
</LinearLayout>
ขั้นตอนที่ 3: โค้ดหลัก (src/MainActivity.java)
package com.example.myapplication;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
TextView textView;
private BroadcastReceiver airplaneModeChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text);
// แสดงสถานะปัจจุบันตอนเริ่มต้น
updateStatus();
}
@Override
protected void onResume() {
super.onResume();
// ลงทะเบียน Receiver เมื่อ Activity Resume
registerReceiver();
}
@Override
protected void onPause() {
super.onPause();
// ยกเลิก Receiver เมื่อ Activity Pause (ป้องกัน Leak)
unregisterReceiver();
}
private void registerReceiver() {
if (airplaneModeChangeReceiver == null) {
airplaneModeChangeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
// อ่านสถานะใหม่จาก Intent Extra
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
String message = isAirplaneModeOn
? "✈️ Airplane Mode เปิดแล้ว"
: "📱 Airplane Mode ปิดแล้ว";
textView.setText(message);
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
// อัปเดตสถานะล่าสุดจาก Settings (Double-check)
updateStatus();
}
}
};
}
IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
registerReceiver(airplaneModeChangeReceiver, filter);
}
private void unregisterReceiver() {
if (airplaneModeChangeReceiver != null) {
try {
unregisterReceiver(airplaneModeChangeReceiver);
} catch (IllegalArgumentException e) {
// Receiver not registered - ignore
}
airplaneModeChangeReceiver = null;
}
}
private void updateStatus() {
boolean isAirplaneModeOn = Settings.Global.getInt(
getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON,
0
) == 1;
String status = isAirplaneModeOn ? "เปิด (ON)" : "ปิด (OFF)";
textView.setText("สถานะปัจจุบัน: Airplane Mode " + status);
}
}
ความแตกต่าง: ACTION_AIRPLANE_MODE vs ACTION_AIRPLANE_MODE_CHANGED
| Action | Trigger เมื่อ | Extra "state" |
|---|---|---|
| Boot completed, Airplane mode changed | มี (API 17+) | |
Intent.ACTION_AIRPLANE_MODE_CHANGED | Airplane mode changed โดยผู้ใช้ | มี (Always) |
แนะนำใช้ ACTION_AIRPLANE_MODE_CHANGED เพราะเฉพาะเจาะจงกว่า และมี Extra state เสมอ
Manifest Declaration (Optional - สำหรับ System-wide Listener)
<receiver android:name=".AirplaneModeReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE_CHANGED" />
</intent-filter>
</receiver>
วิธีนี้ Receiver จะทำงานแม้แอปจะไม่ได้รัน (แต่ต้องจัดการเองใน onReceive)
กรณีการใช้งานจริง
- Offline-first Apps: Sync ข้อมูลเมื่อกลับมาออนไลน์ (Airplane mode ปิด)
- Messaging Apps: แจ้งเตือนผู้ใช้ว่าอยู่ในโหมดออฟไลน์
- Navigation Apps: หยุดดาวน์โหลดแผนที่/อัปเดตตำแหน่งเมื่อ Airplane mode เปิด
- IoT/Remote Control: แจ้งว่าอุปกรณ์ควบคุมไม่อาจเชื่อมต่อได้
- Battery Saver: ปิด Background sync เมื่อ Airplane mode เปิด
ข้อควรระวัง
- Broadcast นี้เป็น Sticky Broadcast - ได้รับค่าล่าสุดทันทีเมื่อ Register
- ต้อง Unregister ใน onPause/onDestroy เพื่อป้องกัน Memory Leak
- ไม่สามารถป้องกัน/บล็อกการเปลี่ยน Airplane Mode ได้ (System-level)
- บาง OEM อาจส่ง Broadcast ซ้ำ หรือไม่ส่ง (Test บนอุปกรณ์จริง)
- Android 10+ จำกัด Broadcast บางประเภท แต่นี้ยังทำงานปกติ
ตัวอย่าง: จัดการ Offline/Online State
public class NetworkStateManager {
private boolean isAirplaneModeOn = false;
private boolean hasNetworkConnection = false;
public void onAirplaneModeChanged(boolean enabled) {
isAirplaneModeOn = enabled;
updateAppBehavior();
}
public void onNetworkChanged(boolean connected) {
hasNetworkConnection = connected;
updateAppBehavior();
}
private void updateAppBehavior() {
if (isAirplaneModeOn || !hasNetworkConnection) {
// Offline mode: ใช้ Cache, Queue requests, Disable sync
enableOfflineMode();
} else {
// Online mode: Sync data, Enable real-time features
enableOnlineMode();
}
}
}