ภาพรวมการออกอากาศ

แอป Android ส่งและรับข้อความประกาศจากระบบ Android และแอป Android อื่นๆ ซึ่งคล้ายกับรูปแบบการออกแบบเผยแพร่-สมัครรับข้อมูล โดยปกติแล้ว ระบบและแอปจะส่งการออกอากาศเมื่อมีเหตุการณ์บางอย่างเกิดขึ้น เช่น ระบบ Android จะส่งการออกอากาศเมื่อมีเหตุการณ์ต่างๆ เกิดขึ้นในระบบ เช่น การบูตระบบหรือการชาร์จอุปกรณ์ นอกจากนี้ แอปยังส่งการออกอากาศที่กำหนดเองด้วย เช่น เพื่อแจ้งให้แอปอื่นๆ ทราบเกี่ยวกับสิ่งที่อาจสนใจ (เช่น การดาวน์โหลดข้อมูลใหม่)

แอปสามารถลงทะเบียนเพื่อรับการออกอากาศที่เฉพาะเจาะจงได้ เมื่อส่งการออกอากาศ ระบบจะกำหนดเส้นทางการออกอากาศไปยังแอปที่สมัครรับการออกอากาศประเภทนั้นโดยอัตโนมัติ

โดยทั่วไปแล้ว คุณสามารถใช้เป็นระบบการรับส่งข้อความในแอปต่างๆ และนอกเส้นทางปกติของผู้ใช้ อย่างไรก็ตาม คุณต้องระมัดระวังอย่าใช้โอกาสในการตอบกลับการออกอากาศและเรียกใช้งานในเบื้องหลังในทางที่ผิด ซึ่งอาจทําให้ระบบทำงานช้า

เกี่ยวกับประกาศของระบบ

ระบบจะส่งการออกอากาศโดยอัตโนมัติเมื่อเกิดเหตุการณ์ต่างๆ ของระบบ เช่น เมื่อระบบเปิดและปิดโหมดบนเครื่องบิน แอปที่สมัครรับข้อมูลทั้งหมดจะได้รับการออกอากาศเหล่านี้

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีอ่าน 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 คุณจะได้รับข้อความประกาศตราบใดที่กิจกรรมยังคงทำงานอยู่ หากลงทะเบียนด้วยบริบทแอปพลิเคชัน คุณจะได้รับการออกอากาศตราบใดที่แอปทำงานอยู่

หากต้องการลงทะเบียนตัวรับที่มีบริบท ให้ทําตามขั้นตอนต่อไปนี้

  1. ในไฟล์บิลด์ระดับโมดูลของแอป ให้รวมคลัง AndroidX Core เวอร์ชัน 1.9.0 ขึ้นไป

    Groovy

    dependencies {     def core_version = "1.16.0"      // 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-beta02" }

    Kotlin

    dependencies {     val core_version = "1.16.0"      // 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-beta02") }
  2. สร้างอินสแตนซ์ของ BroadcastReceiver

    Kotlin

    val myBroadcastReceiver = MyBroadcastReceiver() 

    Java

    MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver(); 
  3. สร้างอินสแตนซ์ของ IntentFilter

    Kotlin

    val filter = IntentFilter("com.example.snippets.ACTION_UPDATE_DATA") 

    Java

    IntentFilter filter = new IntentFilter("com.example.snippets.ACTION_UPDATE_DATA"); 
  4. เลือกว่าจะส่งออกตัวรับสัญญาณออกอากาศและแสดงให้แอปอื่นๆ ในอุปกรณ์เห็นหรือไม่ หากตัวรับนี้กำลังรับฟังการออกอากาศที่ส่งจากระบบหรือจากแอปอื่นๆ รวมถึงแอปอื่นๆ ที่คุณเป็นเจ้าของ ให้ใช้ Flag RECEIVER_EXPORTED หากตัวรับนี้คอยฟังเฉพาะการออกอากาศที่ส่งโดยแอปของคุณ ให้ใช้ Flag RECEIVER_NOT_EXPORTED

    Kotlin

    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; 
  5. ลงทะเบียนผู้รับโดยโทรไปที่ registerReceiver()

    Kotlin

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags) 

    Java

    ContextCompat.registerReceiver(context, myBroadcastReceiver, filter, receiverFlags); 
  6. หากต้องการหยุดรับการออกอากาศ ให้โทรไปที่ unregisterReceiver(android.content.BroadcastReceiver) อย่าลืมยกเลิกการลงทะเบียนตัวรับเมื่อไม่จําเป็นต้องใช้อีกต่อไปหรือบริบทใช้งานไม่ได้แล้ว

ยกเลิกการลงทะเบียน 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     } } 

ลงทะเบียนตัวรับในขอบเขตที่เล็กที่สุด

คุณควรลงทะเบียนตัวรับการออกอากาศเฉพาะในกรณีที่คุณสนใจผลลัพธ์จริงๆ เลือกขอบเขตผู้รับที่เล็กที่สุดเท่าที่จะเป็นไปได้ ดังนี้

  • LifecycleResumeEffect หรือวิธีการเกี่ยวกับวงจรชีวิตของกิจกรรม onResume/onPause: ตัวรับการออกอากาศจะได้รับการอัปเดตเฉพาะในขณะที่แอปอยู่ในสถานะ "กลับมาทํางานอีกครั้ง"
  • LifecycleStartEffect หรือวิธีการเกี่ยวกับวงจรชีวิตของกิจกรรม onStart/onStop: ตัวรับการออกอากาศจะได้รับการอัปเดตเฉพาะในขณะที่แอปอยู่ในสถานะ "กลับมาทํางานอีกครั้ง"
  • DisposableEffect: Broadcast Receiver จะได้รับการอัปเดตก็ต่อเมื่อคอมโพสิชันอยู่ในต้นไม้การคอมโพสิชันเท่านั้น ขอบเขตนี้ไม่ได้แนบอยู่กับขอบเขตวงจรกิจกรรม ลองลงทะเบียนผู้รับในบริบทแอปพลิเคชัน เนื่องจากในทางทฤษฎีแล้ว Composable อาจอยู่ได้นานกว่าขอบเขตวงจรชีวิตของกิจกรรมและทำให้กิจกรรมรั่วไหล
  • กิจกรรม onCreate/onDestroy: ตัวรับการออกอากาศจะได้รับการอัปเดตขณะที่กิจกรรมอยู่ในสถานะ "สร้างแล้ว" อย่าลืมยกเลิกการลงทะเบียนใน onDestroy() ไม่ใช่ onSaveInstanceState(Bundle) เนื่องจากระบบอาจไม่เรียกใช้
  • ขอบเขตที่กำหนดเอง: เช่น คุณสามารถลงทะเบียนตัวรับในViewModel ขอบเขตเพื่อให้ตัวรับยังคงอยู่หลังจากสร้างกิจกรรมใหม่ อย่าลืมใช้บริบทแอปพลิเคชันเพื่อลงทะเบียนตัวรับ เนื่องจากตัวรับอาจอยู่ได้นานกว่าขอบเขตวงจรชีวิตของกิจกรรมและทำให้กิจกรรมรั่วไหล

สร้างคอมโพสิเบิลที่มีสถานะและไม่มีสถานะ

Compose มีคอมโพสิเบิลแบบมีสถานะและแบบไม่มีสถานะ การลงทะเบียนหรือยกเลิกการลงทะเบียน Broadcast Receiver ภายในคอมโพสิเบิลจะทำให้คอมโพสิเบิลมีสถานะ ฟังก์ชันที่ประกอบกันได้ไม่ใช่ฟังก์ชันที่แน่นอนซึ่งแสดงผลเนื้อหาเดียวกันเมื่อส่งพารามิเตอร์เดียวกัน สถานะภายในอาจเปลี่ยนแปลงตามการเรียกใช้ตัวรับสัญญาณออกอากาศที่ลงทะเบียน

แนวทางปฏิบัติแนะนำใน 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

หากคุณประกาศตัวรับการออกอากาศในไฟล์ Manifest ระบบจะเปิดแอปของคุณเมื่อมีการออกอากาศ หากแอปไม่ได้ทำงานอยู่ ระบบจะเปิดแอป

หากต้องการประกาศตัวรับการออกอากาศในไฟล์ Manifest ให้ทําตามขั้นตอนต่อไปนี้

  1. ระบุองค์ประกอบ <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 จะระบุการดำเนินการของ Broadcast ที่ตัวรับสมัครรับข้อมูล

  2. คลาสย่อย BroadcastReceiver และนำไปใช้ onReceive(Context, Intent) ตัวรับการออกอากาศในตัวอย่างต่อไปนี้จะบันทึกและแสดงเนื้อหาของการออกอากาศ

    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() เพื่อเพิ่มทรัพยากรให้กับกระบวนการอื่นๆ ที่สำคัญกว่า กรณีนี้พบได้ทั่วไปในแอปที่ผู้ใช้ไม่เคยหรือไม่ได้โต้ตอบด้วยเมื่อเร็วๆ นี้

ดังนั้น ตัวรับการออกอากาศไม่ควรเริ่มต้นเธรดเบื้องหลังที่ทำงานเป็นเวลานาน ระบบสามารถหยุดกระบวนการได้ทุกเมื่อหลังจาก 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 ของแอปและระบุเหตุการณ์การออกอากาศที่ไม่ซ้ำกัน คุณสามารถแนบข้อมูลเพิ่มเติมไปกับความตั้งใจได้โดยใช้ 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> โปรดดูข้อมูลเกี่ยวกับสิทธิ์และความปลอดภัยโดยทั่วไปที่หัวข้อสิทธิ์ของระบบ

รับการออกอากาศที่มีสิทธิ์

หากคุณระบุพารามิเตอร์สิทธิ์เมื่อลงทะเบียนตัวรับการออกอากาศ (ไม่ว่าจะใช้แท็ก 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> 

หรือแอปที่รับของคุณมี 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" /> 

ข้อควรพิจารณาด้านความปลอดภัย

ข้อควรพิจารณาด้านความปลอดภัยในการส่งและรับการออกอากาศมีดังนี้

  • หากแอปหลายแอปลงทะเบียนเพื่อรับการออกอากาศเดียวกันในไฟล์ Manifest อาจทำให้ระบบเปิดแอปหลายแอป ซึ่งส่งผลอย่างมากต่อทั้งประสิทธิภาพของอุปกรณ์และประสบการณ์ของผู้ใช้ หากต้องการหลีกเลี่ยงปัญหานี้ ให้ใช้การลงทะเบียนบริบทแทนการประกาศไฟล์ Manifest บางครั้งระบบ Android จะบังคับใช้ตัวรับที่ลงทะเบียนตามบริบท เช่น ระบบจะส่งการออกอากาศ CONNECTIVITY_ACTION ไปยังผู้รับที่ลงทะเบียนตามบริบทเท่านั้น

  • อย่าเผยแพร่ข้อมูลที่ละเอียดอ่อนโดยใช้ Intent ที่ไม่ชัดแจ้ง แอปใดก็ได้จะอ่านข้อมูลได้หากลงทะเบียนเพื่อรับการออกอากาศ คุณควบคุมผู้ที่สามารถรับการออกอากาศของคุณได้ 3 วิธีดังนี้

    • คุณสามารถระบุสิทธิ์เมื่อส่งการประกาศได้
    • ใน Android 4.0 (API ระดับ 14) ขึ้นไป คุณสามารถระบุแพ็กเกจด้วย setPackage(String) เมื่อส่งการออกอากาศ ระบบจะจำกัดการออกอากาศไว้ที่ชุดแอปที่ตรงกับแพ็กเกจ
  • เมื่อคุณลงทะเบียนตัวรับ แอปใดก็ได้ที่จะส่งการออกอากาศที่อาจเป็นอันตรายไปยังตัวรับของแอปคุณ การจํากัดการออกอากาศที่แอปของคุณได้รับทำได้หลายวิธีดังนี้

    • คุณสามารถระบุสิทธิ์เมื่อลงทะเบียนตัวรับการออกอากาศได้
    • สําหรับตัวรับที่ประกาศในไฟล์ Manifest คุณสามารถตั้งค่าแอตทริบิวต์ android:exported เป็น "false" ในไฟล์ Manifest ได้ ผู้รับจะไม่ได้รับการออกอากาศจากแหล่งที่มาภายนอกแอป
  • เนมสเปซสําหรับการดําเนินการแบบออกอากาศเป็นแบบส่วนกลาง ตรวจสอบว่าชื่อการดำเนินการและสตริงอื่นๆ เขียนในเนมสเปซที่คุณเป็นเจ้าของ ไม่เช่นนั้นคุณอาจรบกวนแอปอื่นๆ โดยไม่ได้ตั้งใจ

  • เนื่องจากเมธอด onReceive(Context, Intent) ของผู้รับทำงานบนเธรดหลัก จึงควรดำเนินการและแสดงผลอย่างรวดเร็ว หากต้องทํางานเป็นเวลานาน โปรดระมัดระวังเกี่ยวกับการสร้างเธรดหรือเริ่มบริการที่ทำงานอยู่เบื้องหลัง เนื่องจากระบบอาจหยุดทั้งกระบวนการหลังจาก onReceive() แสดงผล ดูข้อมูลเพิ่มเติมได้ที่ผลต่อสถานะกระบวนการ หากต้องการทำงานที่ทำงานต่อเนื่องเป็นเวลานาน เราขอแนะนําให้ทำดังนี้

    • การเรียกใช้ goAsync() ในเมธอด onReceive() ของผู้รับ และส่ง BroadcastReceiver.PendingResult ไปยังเธรดเบื้องหลัง ซึ่งจะทำให้การออกอากาศทำงานต่อไปได้หลังจากกลับมาจากonReceive() อย่างไรก็ตาม แม้จะใช้วิธีนี้ ระบบก็คาดหวังให้คุณออกอากาศให้เสร็จสิ้นอย่างรวดเร็ว (ภายใน 10 วินาที) แต่คุณสามารถย้ายงานไปยังชุดข้อความอื่นได้เพื่อหลีกเลี่ยงข้อบกพร่องของชุดข้อความหลัก
    • การกำหนดเวลางานด้วย JobScheduler ดูข้อมูลเพิ่มเติมได้ที่การกำหนดเวลางานอัจฉริยะ
  • อย่าเริ่มกิจกรรมจากตัวรับการออกอากาศเนื่องจากประสบการณ์ของผู้ใช้จะแย่ลง โดยเฉพาะอย่างยิ่งหากมีตัวรับมากกว่า 1 ตัว แต่ให้พิจารณาแสดงการแจ้งเตือนแทน