แอป Android จะส่งและรับข้อความประกาศจากระบบ Android และแอป Android อื่นๆ ในลักษณะเดียวกับรูปแบบการออกแบบการเผยแพร่-สมัครรับข้อมูล โดยปกติแล้ว ระบบและแอปจะส่งการบรอดแคสต์เมื่อเกิดเหตุการณ์บางอย่าง ตัวอย่างเช่น ระบบ Android จะส่งการบรอดแคสต์เมื่อเกิดเหตุการณ์ต่างๆ ของระบบ เช่น การบูตระบบหรือการชาร์จอุปกรณ์ นอกจากนี้ แอปยังส่งการบรอดแคสต์ที่กำหนดเองด้วย เช่น เพื่อแจ้งให้แอปอื่นๆ ทราบถึงสิ่งที่อาจเป็นที่สนใจ (เช่น การดาวน์โหลดข้อมูลใหม่)
แอปสามารถลงทะเบียนเพื่อรับการบรอดแคสต์ที่เฉพาะเจาะจงได้ เมื่อมีการส่งการบรอดแคสต์ ระบบจะกำหนดเส้นทางการบรอดแคสต์ไปยังแอปที่สมัครรับข้อมูลเพื่อรับการบรอดแคสต์ประเภทนั้นโดยอัตโนมัติ
โดยทั่วไปแล้ว การบรอดแคสต์สามารถใช้เป็นระบบการรับส่งข้อความระหว่างแอปและภายนอกโฟลว์ผู้ใช้ปกติ อย่างไรก็ตาม คุณต้องระมัดระวังไม่ให้ใช้โอกาสในการตอบสนองต่อการบรอดแคสต์และเรียกใช้การทำงานในเบื้องหลังในทางที่ผิด ซึ่งอาจทำให้ประสิทธิภาพของระบบช้าลง
เกี่ยวกับการบรอดแคสต์ของระบบ
ระบบจะส่งการบรอดแคสต์โดยอัตโนมัติเมื่อเกิดเหตุการณ์ต่างๆ ของระบบ เช่น เมื่อระบบเปลี่ยนเข้าและออกจากโหมดบนเครื่องบิน แอปที่สมัครรับข้อมูลทั้งหมดจะได้รับการบรอดแคสต์เหล่านี้
ออบเจ็กต์ Intent จะห่อหุ้มข้อความประกาศ สตริง action จะระบุ
เหตุการณ์ที่เกิดขึ้น เช่น android.intent.action.AIRPLANE_MODE นอกจากนี้ Intent ยังอาจมีข้อมูลเพิ่มเติมที่รวมอยู่ในฟิลด์ Extra
ตัวอย่างเช่น Intent ของโหมดบนเครื่องบินมี Extra แบบบูลีนที่ระบุว่าโหมดบนเครื่องบินเปิดอยู่หรือไม่
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีอ่าน Intent และรับสตริงการดำเนินการจาก Intent ได้ที่ Intent และตัวกรอง Intent
การดำเนินการประกาศของระบบ
ดูรายการการดำเนินการบรอดแคสต์ของระบบทั้งหมดได้ที่ไฟล์ BROADCAST_ACTIONS.TXT ใน Android SDK การดำเนินการบรอดแคสต์แต่ละรายการจะมีฟิลด์ค่าคงที่ที่เชื่อมโยงอยู่ ตัวอย่างเช่น ค่าของค่าคงที่
ACTION_AIRPLANE_MODE_CHANGED คือ android.intent.action.AIRPLANE_MODE
เอกสารประกอบสำหรับการดำเนินการบรอดแคสต์แต่ละรายการมีอยู่ในฟิลด์ค่าคงที่ที่เชื่อมโยง
การเปลี่ยนแปลงประกาศของระบบ
เมื่อแพลตฟอร์ม Android พัฒนาขึ้น แพลตฟอร์มจะเปลี่ยนลักษณะการทำงานของการบรอดแคสต์ของระบบเป็นระยะๆ โปรดคำนึงถึงการเปลี่ยนแปลงต่อไปนี้เพื่อรองรับ Android ทุกเวอร์ชัน
Android 16
ใน Android 16 ไม่รับประกันลำดับการส่งการบรอดแคสต์โดยใช้แอตทริบิวต์ android:priority
หรือ IntentFilter.setPriority() ในกระบวนการต่างๆ
ระบบจะพิจารณาลำดับความสำคัญของการบรอดแคสต์ภายในกระบวนการของแอปพลิเคชันเดียวกันเท่านั้น ไม่ใช่ในทุกกระบวนการ
นอกจากนี้ ระบบยังจำกัดลำดับความสำคัญของการบรอดแคสต์ไว้ในช่วง
(SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1) โดยอัตโนมัติ
เฉพาะคอมโพเนนต์ของระบบเท่านั้นที่ได้รับอนุญาตให้ตั้งค่า SYSTEM_LOW_PRIORITY, SYSTEM_HIGH_PRIORITY เป็นลำดับความสำคัญของการบรอดแคสต์
Android 14
ขณะที่แอปอยู่ในสถานะแคช ระบบจะเพิ่มประสิทธิภาพการส่งการบรอดแคสต์
เพื่อรักษาสภาพระบบให้ดี ตัวอย่างเช่น ระบบจะเลื่อนการบรอดแคสต์ของระบบที่มีความสำคัญน้อยกว่า เช่น ACTION_SCREEN_ON ขณะที่แอปอยู่ในสถานะแคช
เมื่อแอปเปลี่ยนจากสถานะแคชไปเป็นวงจรการทำงานของกระบวนการที่ ใช้งานอยู่
ระบบจะส่งการบรอดแคสต์ที่เลื่อนไว้
การบรอดแคสต์ที่สำคัญซึ่งประกาศไว้ในไฟล์ Manifest จะนำแอปออกจากสถานะแคชชั่วคราว เพื่อส่งการบรอดแคสต์
Android 9
ตั้งแต่ Android 9 (ระดับ API 28) เป็นต้นไป การNETWORK_STATE_CHANGED_ACTION บรอดแคสต์จะไม่ได้รับข้อมูลเกี่ยวกับตำแหน่งของผู้ใช้หรือข้อมูลที่ระบุตัวบุคคลได้
หากแอปของคุณติดตั้งอยู่ในอุปกรณ์ที่ใช้ Android 9.0 (ระดับ API 28) ขึ้นไป ระบบจะไม่รวม SSID, BSSID, ข้อมูลการเชื่อมต่อ หรือผลการสแกนในการบรอดแคสต์ Wi-Fi หากต้องการรับข้อมูลนี้ ให้เรียกใช้
getConnectionInfo() แทน
Android 8.0
ตั้งแต่ Android 8.0 (ระดับ API 26) เป็นต้นไป ระบบจะกำหนดข้อจำกัดเพิ่มเติมสำหรับตัวรับที่ประกาศไว้ในไฟล์ Manifest
หากแอปกำหนดเป้าหมายเป็น Android 8.0 ขึ้นไป คุณจะใช้ไฟล์ Manifest เพื่อ ประกาศตัวรับสำหรับการกระจายข้อมูลแบบไม่เจาะจงปลายทางส่วนใหญ่ (การกระจายข้อมูลที่ไม่ได้กำหนดเป้าหมาย เป็นแอปของคุณโดยเฉพาะ) ไม่ได้ แต่คุณยังคงใช้ตัวรับที่ลงทะเบียนบริบทได้ เมื่อผู้ใช้ใช้แอปของคุณอย่างจริงจัง
Android 7.0
Android 7.0 (API ระดับ 24) ขึ้นไปจะไม่ส่งการบรอดแคสต์ของระบบต่อไปนี้
นอกจากนี้ แอปที่กำหนดเป้าหมายเป็น Android 7.0 ขึ้นไปต้องลงทะเบียนการ
CONNECTIVITY_ACTION บรอดแคสต์โดยใช้
registerReceiver(BroadcastReceiver, IntentFilter) การประกาศตัวรับในไฟล์ Manifest จะใช้ไม่ได้
รับการบรอดแคสต์
แอปสามารถรับการบรอดแคสต์ได้ 2 วิธี ได้แก่ ผ่านตัวรับที่ลงทะเบียนบริบทและตัวรับที่ประกาศไว้ในไฟล์ Manifest
ตัวรับที่ลงทะเบียนบริบท
ตัวรับที่ลงทะเบียนบริบทจะได้รับการบรอดแคสต์ตราบใดที่บริบทการลงทะเบียนยังคงถูกต้อง โดยปกติแล้ว การลงทะเบียนจะเกิดขึ้นระหว่างการเรียกใช้ registerReceiver และ
unregisterReceiver นอกจากนี้ บริบทการลงทะเบียนจะกลายเป็นไม่ถูกต้องเมื่อระบบทำลายบริบทที่เกี่ยวข้อง ตัวอย่างเช่น หากคุณลงทะเบียนภายใน
บริบท Activity คุณจะได้รับการบรอดแคสต์ตราบใดที่กิจกรรม
ยังคงใช้งานอยู่ หากคุณลงทะเบียนด้วยบริบทแอปพลิเคชัน คุณจะได้รับการบรอดแคสต์ตราบใดที่แอปทำงานอยู่
หากต้องการลงทะเบียนตัวรับด้วยบริบท ให้ทำตามขั้นตอนต่อไปนี้
ในไฟล์บิลด์ระดับโมดูลของแอป ให้รวมไลบรารี AndroidX Core เวอร์ชัน 1.9.0 ขึ้นไป:
Groovy
dependencies { def core_version = "1.19.1" // Java language implementation implementation "androidx.core:core:$core_version" // Kotlin implementation "androidx.core:core-ktx:$core_version" // To use RoleManagerCompat implementation "androidx.core:core-role:1.1.0" // To use the Animator APIs implementation "androidx.core:core-animation:1.0.0" // To test the Animator APIs androidTestImplementation "androidx.core:core-animation-testing:1.0.0" // Optional - To enable APIs that query the performance characteristics of GMS devices. implementation "androidx.core:core-performance:1.0.0" // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google implementation "androidx.core:core-google-shortcuts:1.1.0" // Optional - to support backwards compatibility of RemoteViews implementation "androidx.core:core-remoteviews:1.1.0" // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12 implementation "androidx.core:core-splashscreen:1.2.0" }
Kotlin
dependencies { val core_version = "1.19.1" // Java language implementation implementation("androidx.core:core:$core_version") // Kotlin implementation("androidx.core:core-ktx:$core_version") // To use RoleManagerCompat implementation("androidx.core:core-role:1.1.0") // To use the Animator APIs implementation("androidx.core:core-animation:1.0.0") // To test the Animator APIs androidTestImplementation("androidx.core:core-animation-testing:1.0.0") // Optional - To enable APIs that query the performance characteristics of GMS devices. implementation("androidx.core:core-performance:1.0.0") // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google implementation("androidx.core:core-google-shortcuts:1.1.0") // Optional - to support backwards compatibility of RemoteViews implementation("androidx.core:core-remoteviews:1.1.0") // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12 implementation("androidx.core:core-splashscreen:1.2.0") }
สร้างอินสแตนซ์ของ
BroadcastReceiver:Kotlin
val myBroadcastReceiver = MyBroadcastReceiver()Java
MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();สร้างอินสแตนซ์ของ
IntentFilter:Kotlin
val filter = IntentFilter("com.example.snippets.ACTION_UPDATE_DATA")Java
IntentFilter filter = new IntentFilter("com.example.snippets.ACTION_UPDATE_DATA");เลือกว่าจะส่งออก Broadcast Receiver และให้แอปอื่นๆ ในอุปกรณ์มองเห็นได้หรือไม่ หากตัวรับนี้กำลังรอรับการบรอดแคสต์ที่ส่งจากระบบหรือจากแอปอื่นๆ แม้แต่แอปอื่นๆ ที่คุณเป็นเจ้าของ ให้ใช้แฟล็ก
RECEIVER_EXPORTEDแต่หากตัวรับนี้กำลังรอรับการบรอดแคสต์ที่ส่งโดยแอปของคุณเท่านั้น ให้ใช้แฟล็กRECEIVER_NOT_EXPORTEDKotlin
val listenToBroadcastsFromOtherApps = false val receiverFlags = if (listenToBroadcastsFromOtherApps) { ContextCompat.RECEIVER_EXPORTED } else { ContextCompat.RECEIVER_NOT_EXPORTED }Java
boolean listenToBroadcastsFromOtherApps = false; int receiverFlags = listenToBroadcastsFromOtherApps ? ContextCompat.RECEIVER_EXPORTED : ContextCompat.RECEIVER_NOT_EXPORTED;ลงทะเบียนตัวรับโดยเรียกใช้
registerReceiver()Kotlin
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags)Java
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags);หากต้องการหยุดรับการบรอดแคสต์ ให้เรียกใช้
unregisterReceiver(android.content.BroadcastReceiver)อย่าลืมยกเลิกการลงทะเบียนตัวรับเมื่อไม่ต้องการตัวรับนั้นอีกต่อไปหรือบริบทไม่ถูกต้องอีกต่อไป
ยกเลิกการลงทะเบียน Broadcast Receiver ของคุณ
ขณะที่ Broadcast Receiver ลงทะเบียนอยู่ ตัวรับจะเก็บข้อมูลอ้างอิงถึงบริบทที่คุณลงทะเบียนไว้ ซึ่งอาจทำให้เกิดการรั่วไหลหากขอบเขตที่ลงทะเบียนของตัวรับเกินขอบเขตวงจรการทำงานของบริบท ตัวอย่างเช่น เหตุการณ์นี้อาจเกิดขึ้นเมื่อคุณลงทะเบียนตัวรับในขอบเขตกิจกรรม แต่ลืมยกเลิกการลงทะเบียนเมื่อระบบทำลายกิจกรรม ดังนั้น ให้ยกเลิกการลงทะเบียน Broadcast Receiver เสมอ
Kotlin
class MyActivity : ComponentActivity() {
private val myBroadcastReceiver = MyBroadcastReceiver()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// ...
ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags)
setContent { MyApp() }
}
override fun onDestroy() {
super.onDestroy()
// When you forget to unregister your receiver here, you're causing a leak!
this.unregisterReceiver(myBroadcastReceiver)
}
}
Java
class MyActivity extends ComponentActivity {
MyBroadcastReceiver myBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
ContextCompat.registerReceiver(this, myBroadcastReceiver, filter, receiverFlags);
// Set content
}
}
ลงทะเบียนตัวรับในขอบเขตที่เล็กที่สุด
คุณควรลงทะเบียน Broadcast Receiver ก็ต่อเมื่อสนใจผลลัพธ์จริงๆ เลือกขอบเขตตัวรับที่เล็กที่สุดเท่าที่จะเป็นไปได้
LifecycleResumeEffectหรือเมธอดวงจรกิจกรรมonResume/onPauseของกิจกรรม: Broadcast Receiver จะได้รับการอัปเดตเฉพาะขณะที่แอปอยู่ในสถานะกลับมาทำงานต่อLifecycleStartEffectหรือเมธอดวงจรกิจกรรมonStart/onStopของกิจกรรม: Broadcast Receiver จะได้รับการอัปเดตเฉพาะขณะที่แอปอยู่ในสถานะกลับมาทำงานต่อDisposableEffect: Broadcast Receiver จะได้รับการอัปเดตเฉพาะขณะที่ Composable อยู่ในแผนผัง Composition ขอบเขตนี้ไม่ได้แนบอยู่กับขอบเขตวงจรกิจกรรม พิจารณาลงทะเบียนตัวรับในบริบทแอปพลิเคชัน เนื่องจากในทางทฤษฎีแล้ว Composable อาจมีอายุการใช้งานยาวนานกว่าขอบเขตวงจรกิจกรรมและทำให้เกิดการรั่วไหลของกิจกรรมonCreate/onDestroyของกิจกรรม: Broadcast Receiver จะได้รับการอัปเดตขณะที่กิจกรรมอยู่ในสถานะสร้าง อย่าลืมยกเลิกการลงทะเบียนในonDestroy()ไม่ใช่onSaveInstanceState(Bundle)เนื่องจากระบบอาจไม่เรียกใช้เมธอดนี้- ขอบเขตที่กำหนดเอง: ตัวอย่างเช่น คุณสามารถลงทะเบียนตัวรับในขอบเขต
ViewModelเพื่อให้ตัวรับยังคงอยู่ได้แม้จะมีการสร้างกิจกรรมขึ้นใหม่ อย่าลืมใช้บริบทแอปพลิเคชันเพื่อลงทะเบียนตัวรับ เนื่องจากตัวรับอาจมีอายุการใช้งานยาวนานกว่าขอบเขตวงจรการทำงานของกิจกรรมและทำให้เกิดการรั่วไหลของกิจกรรม
สร้างคอมโพสได้แบบมีสถานะและไม่มีสถานะ
Compose มี Composable แบบเก็บสถานะและไม่เก็บสถานะ การลงทะเบียนหรือยกเลิกการลงทะเบียน Broadcast Receiver ภายใน Composable จะทำให้ Composable นั้นเก็บสถานะ คอมโพสได้ไม่ใช่ฟังก์ชันที่กำหนดได้ซึ่งแสดงผลเนื้อหาเดียวกันเมื่อส่งพารามิเตอร์เดียวกัน สถานะภายในอาจเปลี่ยนแปลงตามการเรียกใช้ตัวรับการบรอดแคสต์ที่ลงทะเบียนไว้
แนวทางปฏิบัติแนะนำใน Compose คือการแยก Composable ออกเป็นเวอร์ชันแบบเก็บสถานะและไม่เก็บสถานะ ดังนั้น เราขอแนะนำให้คุณยกการสร้างตัวรับการบรอดแคสต์ออกจากคอมโพสได้เพื่อให้ตัวรับไม่มีสถานะ
@Composable
fun MyStatefulScreen() {
val myBroadcastReceiver = remember { MyBroadcastReceiver() }
val context = LocalContext.current
LifecycleStartEffect(true) {
// ...
ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, flags)
onStopOrDispose { context.unregisterReceiver(myBroadcastReceiver) }
}
MyStatelessScreen()
}
@Composable
fun MyStatelessScreen() {
// Implement your screen
}
ตัวรับที่ประกาศไว้ในไฟล์ Manifest
หากคุณประกาศ Broadcast Receiver ในไฟล์ Manifest ระบบจะเปิดแอปเมื่อมีการส่งการบรอดแคสต์ หากแอปยังไม่ได้ทำงาน ระบบจะเปิดแอป
หากต้องการประกาศ Broadcast Receiver ในไฟล์ Manifest ให้ทำตามขั้นตอนต่อไปนี้
ระบุองค์ประกอบ
<receiver>ในไฟล์ Manifest ของแอป<!-- If this receiver listens for broadcasts sent from the system or from other apps, even other apps that you own, set android:exported to "true". --> <receiver android:name=".MyBroadcastReceiver" android:exported="false"> <intent-filter> <action android:name="com.example.snippets.ACTION_UPDATE_DATA" /> </intent-filter> </receiver>ตัวกรอง Intent จะระบุการดำเนินการประกาศที่ตัวรับสมัครรับข้อมูล
สร้างคลาสย่อย
BroadcastReceiverและใช้onReceive(Context, Intent)Broadcast Receiver ในตัวอย่างต่อไปนี้จะบันทึกและแสดงเนื้อหาของการบรอดแคสต์Kotlin
class MyBroadcastReceiver : BroadcastReceiver() { @Inject lateinit var dataRepository: DataRepository override fun onReceive(context: Context, intent: Intent) { if (intent.action == "com.example.snippets.ACTION_UPDATE_DATA") { val data = intent.getStringExtra("com.example.snippets.DATA") ?: "No data" // Do something with the data, for example send it to a data repository: dataRepository.updateData(data) } } }Java
public static class MyBroadcastReceiver extends BroadcastReceiver { @Inject DataRepository dataRepository; @Override public void onReceive(Context context, Intent intent) { if (Objects.equals(intent.getAction(), "com.example.snippets.ACTION_UPDATE_DATA")) { String data = intent.getStringExtra("com.example.snippets.DATA"); // Do something with the data, for example send it to a data repository: if (data != null) { dataRepository.updateData(data); } } } }
ตัวจัดการแพ็กเกจของระบบจะลงทะเบียนตัวรับเมื่อมีการติดตั้งแอป จากนั้นตัวรับจะกลายเป็นจุดเริ่มต้นแยกต่างหากในแอป ซึ่งหมายความว่าระบบจะเริ่มแอปและส่งการบรอดแคสต์ได้หากแอปไม่ได้ทำงานอยู่
ระบบจะสร้างออบเจ็กต์คอมโพเนนต์ BroadcastReceiver ใหม่เพื่อจัดการ
การบรอดแคสต์แต่ละรายการที่ได้รับ ออบเจ็กต์นี้จะใช้ได้เฉพาะในระหว่าง
การเรียกใช้ onReceive(Context, Intent) เท่านั้น เมื่อโค้ดของคุณกลับมาจากเมธอดนี้ ระบบจะถือว่าคอมโพเนนต์ไม่ได้ใช้งานอีกต่อไป
ผลกระทบต่อสถานะกระบวนการ
ไม่ว่า BroadcastReceiver จะทำงานอยู่หรือไม่ก็ตาม จะส่งผลต่อกระบวนการที่มีอยู่
ซึ่งอาจเปลี่ยนโอกาสที่ระบบจะหยุดกระบวนการนั้น กระบวนการที่ทำงานอยู่เบื้องหน้า
จะเรียกใช้เมธอด onReceive() ของตัวรับ ระบบจะเรียกใช้กระบวนการดังกล่าว ยกเว้นในกรณีที่หน่วยความจำใกล้เต็ม
ระบบจะปิดใช้งาน BroadcastReceiver หลังจาก onReceive()
ความสำคัญของกระบวนการโฮสต์ของตัวรับจะขึ้นอยู่กับคอมโพเนนต์ของแอป หากกระบวนการนั้นโฮสต์เฉพาะตัวรับที่ประกาศไว้ในไฟล์ Manifest ระบบอาจหยุดกระบวนการนั้นหลังจาก onReceive() เพื่อเพิ่มทรัพยากรให้กับกระบวนการอื่นๆ ที่สำคัญกว่า ซึ่งเป็นเรื่องปกติสำหรับแอปที่ผู้ใช้ไม่เคยโต้ตอบด้วยหรือไม่ได้โต้ตอบด้วยเมื่อเร็วๆ นี้
ดังนั้น Broadcast Receiver จึงไม่ควรเริ่มเทรดเบื้องหลังที่ทำงานเป็นเวลานาน
ระบบสามารถหยุดกระบวนการได้ทุกเมื่อหลังจาก onReceive() เพื่อเรียกคืนหน่วยความจำ ซึ่งจะยุติเทรดที่สร้างขึ้น หากต้องการให้กระบวนการทำงานอยู่ ให้กำหนดเวลา
JobService จากตัวรับโดยใช้ JobScheduler เพื่อให้ระบบทราบว่ากระบวนการยังคงทำงานอยู่ ภาพรวมการทำงานเบื้องหลัง
ให้รายละเอียดเพิ่มเติม
ส่งการบรอดแคสต์
Android มี 2 วิธีให้แอปส่งการบรอดแคสต์ ดังนี้
- เมธอด
sendOrderedBroadcast(Intent, String)จะส่งการบรอดแคสต์ไปยัง ตัวรับทีละรายการ เมื่อตัวรับแต่ละรายการทำงานตามลำดับ ตัวรับจะส่งต่อผลลัพธ์ไปยังตัวรับถัดไปได้ นอกจากนี้ ตัวรับยังยกเลิกการบรอดแคสต์โดยสมบูรณ์ได้เพื่อไม่ให้การบรอดแคสต์ไปถึงตัวรับอื่นๆ คุณสามารถควบคุมลำดับที่ตัวรับทำงานภายในกระบวนการของแอปเดียวกันได้ โดยใช้แอตทริบิวต์android:priorityของ Intent Filter ที่ตรงกัน ตัวรับที่มีลำดับความสำคัญเท่ากันจะทำงานตามลำดับที่กำหนด - เมธอด
sendBroadcast(Intent)จะส่งการบรอดแคสต์ไปยังตัวรับทั้งหมด ตามลำดับที่ ไม่ได้กำหนด ซึ่งเรียกว่าการบรอดแคสต์ปกติ วิธีนี้มีประสิทธิภาพมากกว่า แต่หมายความว่าตัวรับจะอ่านผลลัพธ์จากตัวรับอื่นๆ ส่งต่อข้อมูลที่ได้รับจากการบรอดแคสต์ หรือยกเลิกการบรอดแคสต์ไม่ได้
ข้อมูลโค้ดต่อไปนี้แสดงวิธีส่งการบรอดแคสต์โดยการสร้าง
Intent และเรียกใช้ sendBroadcast(Intent)
Kotlin
val intent = Intent("com.example.snippets.ACTION_UPDATE_DATA").apply {
putExtra("com.example.snippets.DATA", newData)
setPackage("com.example.snippets")
}
context.sendBroadcast(intent)
Java
Intent intent = new Intent("com.example.snippets.ACTION_UPDATE_DATA");
intent.putExtra("com.example.snippets.DATA", newData);
intent.setPackage("com.example.snippets");
context.sendBroadcast(intent);
ข้อความประกาศจะรวมอยู่ในออบเจ็กต์ Intent สตริง action ของ Intent ต้องระบุไวยากรณ์ชื่อแพ็กเกจ Java ของแอปและระบุเหตุการณ์บรอดแคสต์ที่ไม่ซ้ำกัน คุณสามารถแนบข้อมูลเพิ่มเติมกับ
Intent ได้ด้วย putExtra(String, Bundle) นอกจากนี้ คุณยังจำกัดการบรอดแคสต์ไว้เฉพาะ
แอปบางแอปในองค์กรเดียวกันได้โดยเรียกใช้ setPackage(String) ใน
Intent
จำกัดการบรอดแคสต์ด้วยสิทธิ์
สิทธิ์ช่วยให้คุณจำกัดการบรอดแคสต์ไว้เฉพาะแอปบางแอปที่มีสิทธิ์บางอย่าง คุณสามารถบังคับใช้ข้อจำกัดกับผู้ส่งหรือผู้รับการบรอดแคสต์ก็ได้
ส่งการบรอดแคสต์ด้วยสิทธิ์
เมื่อเรียกใช้ sendBroadcast(Intent, String) หรือ
sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String,
Bundle)
คุณสามารถระบุพารามิเตอร์สิทธิ์ได้ เฉพาะตัวรับที่ขอสิทธิ์ดังกล่าวด้วยแท็ก <uses-permission> ในไฟล์ Manifest เท่านั้นที่จะได้รับการบรอดแคสต์ หากสิทธิ์เป็นสิทธิ์ที่เป็นอันตราย คุณต้องให้สิทธิ์ก่อนที่ตัวรับจะได้รับการบรอดแคสต์ ตัวอย่างเช่น โค้ดต่อไปนี้จะส่งการบรอดแคสต์พร้อมสิทธิ์
Kotlin
context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION)
Java
context.sendBroadcast(intent, android.Manifest.permission.ACCESS_COARSE_LOCATION);
หากต้องการรับการบรอดแคสต์ แอปที่รับต้องขอสิทธิ์ดังนี้
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
คุณสามารถระบุสิทธิ์ของระบบที่มีอยู่ เช่น
BLUETOOTH_CONNECT หรือกำหนดสิทธิ์ที่กำหนดเองด้วยองค์ประกอบ
<permission> ดูข้อมูลเกี่ยวกับสิทธิ์และความปลอดภัยโดยทั่วไปได้ที่
สิทธิ์ของระบบ
รับการบรอดแคสต์ด้วยสิทธิ์
หากคุณระบุพารามิเตอร์สิทธิ์เมื่อลงทะเบียน Broadcast Receiver (ด้วย registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) หรือใน <receiver> แท็กในไฟล์ Manifest) เฉพาะผู้บรอดแคสต์ที่ขอสิทธิ์ด้วยแท็ก <uses-permission> ในไฟล์ Manifest เท่านั้นที่จะส่ง Intent ไปยังตัวรับได้ หากสิทธิ์เป็นสิทธิ์ที่เป็นอันตราย ผู้บรอดแคสต์ต้องได้รับสิทธิ์ด้วย
ตัวอย่างเช่น สมมติว่าแอปที่รับมีตัวรับที่ประกาศไว้ในไฟล์ Manifest ดังนี้
<!-- If this receiver listens for broadcasts sent from the system or from
other apps, even other apps that you own, set android:exported to "true". -->
<receiver
android:name=".MyBroadcastReceiverWithPermission"
android:permission="android.permission.ACCESS_COARSE_LOCATION"
android:exported="true">
<intent-filter>
<action android:name="com.example.snippets.ACTION_UPDATE_DATA" />
</intent-filter>
</receiver>
หรือแอปที่รับมีตัวรับที่ลงทะเบียนบริบทดังนี้
Kotlin
ContextCompat.registerReceiver(
context, myBroadcastReceiver, filter,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
null, // scheduler that defines thread, null means run on main thread
receiverFlags
)
Java
ContextCompat.registerReceiver(
context, myBroadcastReceiver, filter,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
null, // scheduler that defines thread, null means run on main thread
receiverFlags
);
จากนั้น แอปที่ส่งต้องขอสิทธิ์ดังนี้จึงจะส่งการบรอดแคสต์ไปยังตัวรับเหล่านั้นได้
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
หลีกเลี่ยงการบรอดแคสต์ภายในกระบวนการเดียวกัน
การบรอดแคสต์ได้รับการออกแบบให้เป็นกลไกการสื่อสารระหว่างโปรเซส (IPC) สำหรับการส่งข้อความระหว่างแอปต่างๆ หรือระหว่างระบบกับแอป การส่ง การบรอดแคสต์ด้วยตนเอง ซึ่งเป็นการบรอดแคสต์ที่ตัวรับ ทั้งหมด ของ ตัวรับทำงานในกระบวนการเดียวกันกับที่ส่งการบรอดแคสต์นั้นไม่มีประสิทธิภาพอย่างมาก สร้างค่าใช้จ่ายที่ไม่จำเป็นของระบบ และไม่แนะนำอย่างยิ่ง
สถานการณ์ที่พบบ่อย 2 กรณีที่แอปส่งการบรอดแคสต์ไปยังตัวเอง ได้แก่
การสื่อสารระหว่างคอมโพเนนต์ในกระบวนการเดียวกัน: เช่น การส่งเหตุการณ์หรือข้อมูลระหว่างกิจกรรม, Fragment, บริการ หรือ เทรดเบื้องหลัง ให้ใช้กลไกการสื่อสารมาตรฐานในกระบวนการ เช่น รูปแบบ Observer หรือสตรีมแบบรีแอกทีฟ แทนการส่งการบรอดแคสต์
- Kotlin Flow (
SharedFlowและStateFlow): โซลูชันที่ทันสมัย และเป็นสำนวนใน Kotlin สำหรับการปล่อยและสังเกตสตรีมเหตุการณ์ หรือการอัปเดตสถานะในคอร์รูทีนและคอมโพเนนต์ในแอป ViewModelที่แชร์: ช่วยให้แชร์ข้อมูลและเหตุการณ์ ระหว่างคอมโพเนนต์ UI ต่างๆ (เช่น Fragment หรือคอมโพสได้) ภายในกิจกรรมเดียวกัน- การเรียกกลับและ Listener: การเรียกกลับอินเทอร์เฟซมาตรฐานหรือข้อมูลอ้างอิงฟังก์ชัน ที่ส่งระหว่างคอมโพเนนต์โดยตรง หรือลงทะเบียนกับ ที่เก็บหรือคอนโทรลเลอร์ส่วนกลาง
- Kotlin Flow (
การจัดการเหตุการณ์ของระบบ การทำงาน หรือการปลุก: เช่น การรับการทำงานที่กำหนดเวลาไว้ การปลุก หรือการเรียกกลับของระบบ แล้วส่งการบรอดแคสต์เพื่อทริกเกอร์การทำงานจริง ให้ทำงานให้เสร็จสมบูรณ์โดยตรงภายในงานนั้น (เช่น
JobServiceหรือ Worker ของ WorkManager), ตัวแฮนเดิลการปลุก หรือคอมโพเนนต์การเรียกกลับของระบบ หรือมอบหมายงานไปยังคลาส<b>ตรรกะทางธุรกิจ</b>ของแอปโดยตรง แทนการส่งการบรอดแคสต์
ในอุปกรณ์ที่ใช้ Android 17 QPR2 ขึ้นไป ระบบจะ ส่งการบรอดแคสต์ด้วยตนเองอย่างมีประสิทธิภาพมากขึ้นโดยส่งการบรอดแคสต์กลับไปยัง กระบวนการที่ส่ง ซึ่งจะส่งการบรอดแคสต์ไปยังตัวรับของตนเองในเทรดหลัก การส่งการบรอดแคสต์ด้วยตนเองจะไม่เพิ่มความสำคัญของกระบวนการและจะไม่ป้องกันไม่ให้กระบวนการที่แคชไว้หยุดทำงาน ดังนั้นอย่าใช้การบรอดแคสต์ด้วยตนเองเพื่อให้แอปทำงานอยู่หรือทำงานในเบื้องหลัง แต่ให้เลือก API ที่เหมาะสมกับงานของคุณตามที่อธิบายไว้ใน ภาพรวมของงานเบื้องหลัง แม้จะมีการเพิ่มประสิทธิภาพนี้ การบรอดแคสต์ด้วยตนเองก็มีประสิทธิภาพน้อยกว่ากลไกการสื่อสารในกระบวนการ ดังนั้นให้ใช้ทางเลือกอื่นแทน
ดูข้อมูลเพิ่มเติมเกี่ยวกับการออกแบบการสื่อสารระหว่างคอมโพเนนต์ของแอปได้ที่ คู่มือสถาปัตยกรรมแอป
ข้อควรพิจารณาด้านความปลอดภัย
ข้อควรพิจารณาด้านความปลอดภัยบางประการสำหรับการส่งและรับการบรอดแคสต์มีดังนี้
หากแอปจำนวนมากลงทะเบียนเพื่อรับการบรอดแคสต์เดียวกันในไฟล์ Manifest อาจทำให้ระบบเปิดแอปจำนวนมาก ซึ่งส่งผลกระทบอย่างมากต่อทั้งประสิทธิภาพของอุปกรณ์และประสบการณ์ของผู้ใช้ หากต้องการหลีกเลี่ยงปัญหานี้ ให้ใช้การลงทะเบียนบริบทแทนการประกาศในไฟล์ Manifest บางครั้งระบบ Android เองก็บังคับใช้การใช้ตัวรับที่ลงทะเบียนบริบท ตัวอย่างเช่น การบรอดแคสต์
CONNECTIVITY_ACTIONจะส่งไปยัง ตัวรับที่ลงทะเบียนบริบทเท่านั้นอย่าบรอดแคสต์ข้อมูลที่ละเอียดอ่อนโดยใช้ Intent โดยนัย แอปใดๆ ก็อ่านข้อมูลได้หากลงทะเบียนเพื่อรับการบรอดแคสต์ คุณสามารถควบคุมผู้ที่รับการบรอดแคสต์ได้ 3 วิธี ดังนี้
- คุณสามารถระบุสิทธิ์เมื่อส่งการบรอดแคสต์
- ใน Android 4.0 (ระดับ API 14) ขึ้นไป คุณสามารถระบุa
แพ็กเกจด้วย
setPackage(String)เมื่อส่งการบรอดแคสต์ ระบบจะจำกัดการบรอดแคสต์ไว้เฉพาะแอปบางแอปที่ตรงกับแพ็กเกจ
เมื่อคุณลงทะเบียนตัวรับ แอปใดๆ ก็ส่งการบรอดแคสต์ที่อาจเป็นอันตรายไปยังตัวรับของแอปคุณได้ คุณสามารถจำกัดการบรอดแคสต์ที่แอปได้รับได้หลายวิธี ดังนี้
- คุณสามารถระบุสิทธิ์เมื่อลงทะเบียน Broadcast Receiver
- สำหรับตัวรับที่ประกาศไว้ในไฟล์ Manifest คุณสามารถตั้งค่าแอตทริบิวต์ android:exported เป็น "false" ในไฟล์ Manifest ตัวรับจะไม่ได้รับการบรอดแคสต์จากแหล่งที่มาภายนอกแอป
เนมสเปซสำหรับการดำเนินการบรอดแคสต์เป็นแบบส่วนกลาง ตรวจสอบว่าได้เขียนชื่อการดำเนินการและสตริงอื่นๆ ในเนมสเปซที่คุณเป็นเจ้าของ มิฉะนั้น คุณอาจขัดแย้งกับแอปอื่นๆ โดยไม่ตั้งใจ
เนื่องจากเมธอด
onReceive(Context, Intent)ของตัวรับทำงานใน เทรดหลัก เมธอดจึงควรดำเนินการ และกลับมาอย่างรวดเร็ว หากคุณต้องทำงานที่ใช้เวลานาน ให้ระมัดระวังในการสร้างเทรดหรือเริ่มบริการที่ทำงานอยู่เบื้องหลัง เนื่องจากระบบสามารถหยุดกระบวนการทั้งหมดได้หลังจากonReceive()กลับมา ดูข้อมูลเพิ่มเติมได้ที่ ผลกระทบต่อสถานะกระบวนการ หากต้องการทำงานที่ใช้เวลานาน เราขอแนะนำให้ทำดังนี้- เรียกใช้
goAsync()ในเมธอดonReceive()ของตัวรับและ ส่งBroadcastReceiver.PendingResultไปยังเทรด เบื้องหลัง วิธีนี้จะทำให้การบรอดแคสต์ยังคงใช้งานได้หลังจากกลับมาจากonReceive()อย่างไรก็ตาม แม้จะใช้วิธีนี้ ระบบก็คาดหวังให้คุณทำการบรอดแคสต์ให้เสร็จอย่างรวดเร็ว (ภายใน 10 วินาที) แต่ระบบอนุญาตให้คุณย้ายงานไปยังเทรดอื่นเพื่อหลีกเลี่ยงการเกิดข้อผิดพลาดในเทรดหลัก - กำหนดเวลาการทำงานด้วย
JobSchedulerดูข้อมูลเพิ่มเติมได้ที่ ดู การกำหนดเวลาการทำงานอย่างชาญฉลาด
- เรียกใช้
อย่าเริ่มกิจกรรมจาก Broadcast Receiver เนื่องจากประสบการณ์ของผู้ใช้จะสะดุด โดยเฉพาะอย่างยิ่งหากมี Broadcast Receiver มากกว่า 1 ราย แต่ให้พิจารณา แสดงการแจ้งเตือนแทน