สมมติว่าคุณมีแอปพลิเคชันที่ขึ้นอยู่กับการเชื่อมต่ออินเทอร์เน็ตที่เสถียร คุณต้องการให้แอปพลิเคชันของคุณได้รับการแจ้งเตือนเมื่อการเชื่อมต่ออินเทอร์เน็ตมีการเปลี่ยนแปลง คุณทำอย่างนั้นได้อย่างไร? วิธีแก้ปัญหาที่เป็นไปได้คือบริการที่ตรวจสอบการเชื่อมต่ออินเทอร์เน็ตเสมอ การใช้งานนี้ไม่ดีด้วยเหตุผลหลายประการ ดังนั้นเราจะไม่พิจารณาถึงเรื่องนี้ วิธีแก้ปัญหานี้คือ Broadcast Receiver และมันจะรับฟังการเปลี่ยนแปลงที่คุณบอกให้ทำ ผู้รับการออกอากาศจะได้รับแจ้งการออกอากาศเสมอ โดยไม่คำนึงถึงสถานะของแอปพลิเคชันของคุณ ไม่สำคัญว่าแอปพลิเคชันของคุณกำลังทำงานอยู่ในพื้นหลังหรือไม่ทำงานเลย
พื้นหลัง
เครื่องรับสัญญาณออกอากาศเป็นส่วนประกอบในแอปพลิเคชัน Android ของคุณที่รับฟังข้อความออกอากาศ (หรือเหตุการณ์) จากช่องทางต่างๆ:
- จากแอปพลิเคชันอื่น
- จากระบบเอง
- จากใบสมัครของคุณ
หมายความว่าพวกเขาถูกเรียกใช้เมื่อมีการกระทำบางอย่างเกิดขึ้นที่พวกเขาได้รับการตั้งโปรแกรมให้ฟัง (IE, การออกอากาศ)
การออกอากาศเป็นเพียงข้อความที่อยู่ภายในวัตถุเจตนา การออกอากาศอาจเป็นได้ทั้งโดยปริยายหรือโจ่งแจ้ง
- การออกอากาศโดยนัย เป็นโปรแกรมที่ไม่ได้กำหนดเป้าหมายแอปพลิเคชันของคุณโดยเฉพาะ ดังนั้นจึงไม่ใช่เฉพาะแอปพลิเคชันของคุณ ในการลงทะเบียน คุณต้องใช้ IntentFilter และประกาศในรายการของคุณ คุณต้องทำทั้งหมดนี้เนื่องจากระบบปฏิบัติการ Android จะตรวจสอบตัวกรองความตั้งใจที่ประกาศไว้ทั้งหมดในรายการของคุณและดูว่ามีรายการที่ตรงกันหรือไม่ เนื่องจากลักษณะการทำงานนี้ การออกอากาศโดยนัยจึงไม่มีแอตทริบิวต์เป้าหมาย ตัวอย่างสำหรับการออกอากาศโดยนัยคือการกระทำของข้อความ SMS ที่เข้ามา
- ออกอากาศอย่างโจ่งแจ้ง เป็นเป้าหมายเฉพาะสำหรับแอปพลิเคชันของคุณบนส่วนประกอบที่ทราบล่วงหน้า สิ่งนี้เกิดขึ้นเนื่องจากแอตทริบิวต์เป้าหมายที่มีชื่อแพ็คเกจของแอปพลิเคชันหรือชื่อคลาสส่วนประกอบ
มีสองวิธีในการประกาศผู้รับ:
- โดยการประกาศในไฟล์ AndroidManifest.xml ของคุณด้วยแท็ก
(เรียกอีกอย่างว่าสแตติก)
<receiver android:name=".YourBrodcastReceiverClass" android:exported="true">
<intent-filter>
<!-- The actions you wish to listen to, below is an example -->
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
คุณจะสังเกตเห็นว่าเครื่องรับสัญญาณออกอากาศที่ประกาศข้างต้นมีคุณสมบัติ exported=”true” . คุณลักษณะนี้บอกผู้รับว่าสามารถรับการออกอากาศจากนอกขอบเขตของแอปพลิเคชันได้
2. หรือแบบไดนามิกโดยการลงทะเบียนอินสแตนซ์กับ registerReceiver (เรียกว่า Context Register)
public abstract Intent registerReceiver (BroadcastReceiver receiver,
IntentFilter filter);
การนำไปใช้
ในการสร้างเครื่องรับการออกอากาศของคุณเอง ก่อนอื่นคุณต้องขยายคลาสหลักของ BroadcastReceiver และแทนที่วิธีการบังคับ onReceive:
public void onReceive(Context context, Intent intent) {
//Implement your logic here
}
นำทั้งหมดมารวมกันให้ผลตอบแทน:
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
StringBuilder sb = new StringBuilder();
sb.append("Action: " + intent.getAction() + "\n");
sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n");
String log = sb.toString();
Toast.makeText(context, log, Toast.LENGTH_LONG).show();
}
}
⚠️เมธอด onReceive ทำงานบนเธรดหลัก และด้วยเหตุนี้ การดำเนินการจึงควรสั้น
หากดำเนินการกระบวนการที่ยาวนาน ระบบอาจฆ่ากระบวนการหลังจากที่เมธอดกลับมา เพื่อหลีกเลี่ยงปัญหานี้ ให้ลองใช้ goAsync หรือกำหนดเวลางาน คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการกำหนดเวลางานได้ที่ด้านล่างของบทความนี้
ตัวอย่างการลงทะเบียนแบบไดนามิก
ในการลงทะเบียนผู้รับด้วยบริบท ก่อนอื่นคุณต้องสร้างอินสแตนซ์ของผู้รับการออกอากาศของคุณ:
BroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
จากนั้น คุณสามารถลงทะเบียนได้ขึ้นอยู่กับบริบทเฉพาะที่คุณต้องการ:
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
this.registerReceiver(myBroadcastReceiver, filter);
อย่าลืมยกเลิกการลงทะเบียนเครื่องรับสัญญาณออกอากาศเมื่อไม่ต้องการใช้อีกต่อไป
@Override
protected void onStop() {
super.onStop();
unregisterReceiver(myBroadcastReceiver);
}
การแพร่ภาพเหตุการณ์
เบื้องหลังการออกอากาศข้อความจากแอปพลิเคชันของคุณคือการอนุญาตให้แอปพลิเคชันของคุณตอบสนองต่อเหตุการณ์ที่เกิดขึ้นภายในแอปพลิเคชัน ลองนึกถึงสถานการณ์ที่ผู้ใช้ดำเนินการบางอย่างในส่วนหนึ่งของโค้ด และด้วยเหตุนี้ คุณจึงต้องการดำเนินการตรรกะอื่นๆ ที่คุณมีในที่อื่น
มีสามวิธีในการส่งการออกอากาศ:
- sendOrderedBroadcast วิธีตรวจสอบให้แน่ใจว่าได้ส่งการออกอากาศไปยังเครื่องรับเพียงเครื่องเดียวในแต่ละครั้ง ในทางกลับกัน การออกอากาศแต่ละครั้งสามารถส่งผ่านข้อมูลไปยังผู้ที่ตามมา หรือเพื่อหยุดการเผยแพร่การออกอากาศไปยังผู้รับที่ตามมา
- ส่งออกอากาศ คล้ายกับวิธีการที่กล่าวมาข้างต้น โดยมีข้อแตกต่างประการหนึ่ง ผู้รับการออกอากาศทั้งหมดได้รับข้อความและไม่พึ่งพาซึ่งกันและกัน
- LocalBroadcastManager.sendBroadcast วิธีส่งเฉพาะการออกอากาศไปยังผู้รับที่กำหนดไว้ภายในแอปพลิเคชันของคุณและไม่เกินขอบเขตของแอปพลิเคชันของคุณ ตัวอย่างของการส่งการออกอากาศที่กำหนดเอง
https://giphy.com/gifs/23gUJhHyWkXEwl7UYV/html5
สิ่งที่ควรให้ความสนใจ
- อย่าส่งข้อมูลที่ละเอียดอ่อนผ่านการแพร่ภาพโดยนัย เนื่องจากแอปพลิเคชันใดๆ ที่รับฟังข้อมูลนั้น จะได้รับข้อมูลดังกล่าว คุณสามารถป้องกันได้โดยระบุแพ็คเกจหรือแนบสิทธิ์ในการออกอากาศ
- อย่าเริ่มกิจกรรมจากการออกอากาศที่ได้รับเนื่องจากขาดประสบการณ์ของผู้ใช้ เลือกให้แสดงการแจ้งเตือนแทน
หัวข้อย่อยต่อไปนี้อ้างถึงการเปลี่ยนแปลงในตัวรับการออกอากาศที่เกี่ยวข้องกับระบบปฏิบัติการ Android แต่ละเวอร์ชัน (เริ่มจาก 7.0) สำหรับแต่ละเวอร์ชันมีข้อ จำกัด บางประการและพฤติกรรมก็เปลี่ยนไปเช่นกัน โปรดคำนึงถึงข้อจำกัดเหล่านี้เมื่อนึกถึงการใช้เครื่องรับส่งสัญญาณ
- 7.0 ขึ้นไป (API ระดับ 24) - การออกอากาศสองระบบถูกปิดใช้งาน Action_New_Picture และ Action_New_Video (แต่ถูกนำกลับมาใน Android O สำหรับเครื่องรับที่ลงทะเบียน)
- 8.0 ขึ้นไป (API ระดับ 26) - การออกอากาศโดยนัยส่วนใหญ่จำเป็นต้องลงทะเบียนเป็นแบบไดนามิกและไม่ใช่แบบสแตติก (ในรายการของคุณ) คุณสามารถค้นหาการออกอากาศที่ได้รับอนุญาตพิเศษในลิงก์นี้
- 9.0 ขึ้นไป (API ระดับ 28) - ข้อมูลที่ได้รับน้อยลงในการออกอากาศระบบ Wi-Fi และ Network_State_Changed_Action
การเปลี่ยนแปลงใน Android O คือสิ่งที่คุณต้องระวังมากที่สุด สาเหตุที่ทำการเปลี่ยนแปลงเหล่านี้เนื่องจากนำไปสู่ปัญหาด้านประสิทธิภาพ การใช้งานแบตเตอรี่หมด และส่งผลกระทบต่อประสบการณ์การใช้งานของผู้ใช้ สิ่งนี้เกิดขึ้นเนื่องจากแอปพลิเคชั่นจำนวนมาก (แม้แต่ที่ไม่ได้ทำงานอยู่) กำลังรับฟังการเปลี่ยนแปลงทั้งระบบ และเมื่อการเปลี่ยนแปลงนั้นเกิดขึ้น ความโกลาหลก็บังเกิด ลองนึกภาพว่าทุกแอปพลิเคชันที่ลงทะเบียนในการดำเนินการนั้นมีชีวิตขึ้นมาเพื่อตรวจสอบว่าจำเป็นต้องทำอะไรเนื่องจากการออกอากาศหรือไม่ พิจารณาบางอย่าง เช่น สถานะ Wi-Fi ซึ่งเปลี่ยนแปลงบ่อย แล้วคุณจะเริ่มเข้าใจว่าทำไมการเปลี่ยนแปลงเหล่านี้จึงเกิดขึ้น
ทางเลือกอื่นสำหรับเครื่องรับส่งสัญญาณ
เพื่อให้ง่ายต่อการสำรวจข้อจำกัดเหล่านี้ ด้านล่างนี้คือรายละเอียดของส่วนประกอบอื่นๆ ที่คุณสามารถใช้ได้ในกรณีที่ไม่มีเครื่องรับการออกอากาศ แต่ละคนมีความรับผิดชอบและกรณีการใช้งานที่แตกต่างกัน ดังนั้นลองจับคู่ว่าอันไหนที่เหมาะกับความต้องการของคุณ
- LocalBroadcastManager - ตามที่กล่าวไว้ข้างต้น ใช้ได้เฉพาะการออกอากาศภายในแอปพลิเคชันของคุณเท่านั้น
- การจัดตารางงาน - งานสามารถเรียกใช้ได้ขึ้นอยู่กับสัญญาณหรือทริกเกอร์ที่ได้รับ ดังนั้นคุณอาจพบว่าการออกอากาศที่คุณกำลังฟังอยู่สามารถแทนที่ด้วยงานได้ นอกจากนี้ JobScheduler จะรับประกันว่างานของคุณจะเสร็จสิ้น แต่จะคำนึงถึงปัจจัยต่างๆ ของระบบ (เวลาและเงื่อนไข) เพื่อกำหนดว่าเมื่อใดควรทำงาน เมื่อสร้างงาน คุณจะแทนที่วิธีการที่เรียกว่า onStartJob . วิธีนี้ทำงานบนเธรดหลัก ดังนั้นตรวจสอบให้แน่ใจว่าวิธีนี้ทำงานเสร็จภายในระยะเวลาที่จำกัด หากคุณต้องการใช้ตรรกะที่ซับซ้อน ให้ลองเริ่มงานเบื้องหลัง นอกจากนี้ ค่าส่งคืนสำหรับเมธอดนี้เป็นบูลีน โดยที่ true แสดงว่ายังมีการดำเนินการบางอย่างอยู่ และค่า false หมายความว่างานเสร็จสิ้นแล้ว
หากคุณต้องการสัมผัสกับความสุขและความประหลาดใจที่เป็นเครื่องรับส่งสัญญาณโดยตรง คุณสามารถทำตามลิงก์เหล่านี้ไปยังที่เก็บที่ฉันตั้งไว้:
- การออกอากาศแบบกำหนดเอง (พร้อมการประกาศรายการ)
- การลงทะเบียนการออกอากาศ (โดยไม่ประกาศในรายการ)
- LocalBroadcastManager
ออกอากาศจบแล้ว