แก้ปัญหาบริการที่ทำงานอยู่เบื้องหน้า

หน้านี้จะอธิบายสาเหตุที่พบบ่อยซึ่งทำให้บริการที่ทำงานอยู่เบื้องหน้าทำงานไม่สำเร็จ และช่วยคุณระบุสาเหตุของปัญหา

เอกสารนี้จะกล่าวถึงปัญหาต่อไปนี้

ก่อนแก้ปัญหา

ตรวจสอบการเปลี่ยนแปลงล่าสุดในบริการที่ทำงานอยู่เบื้องหน้า

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

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

  • โค้ดบริการที่ทำงานอยู่เบื้องหน้าที่เคยทำงานได้ก่อนหน้านี้ไม่ทำงานแล้ว
  • คุณเพิ่งเริ่มทดสอบแพลตฟอร์มรุ่นใหม่ หรือคุณได้เปลี่ยนระดับ API ที่แอปกำหนดเป้าหมาย

นอกจากนี้ หากคุณกำลังทดสอบอุปกรณ์ในเวอร์ชันตัวอย่างสำหรับนักพัฒนาซอฟต์แวร์ของแพลตฟอร์ม โปรดตรวจสอบเอกสารประกอบของเวอร์ชันตัวอย่างสำหรับนักพัฒนาซอฟต์แวร์เวอร์ชันล่าสุด

ข้อผิดพลาดแอปพลิเคชันไม่ตอบสนอง (ANR)

ในบางกรณี แอปควรปิดบริการที่ทำงานอยู่เบื้องหน้า หากแอปไม่หยุดบริการ ระบบจะหยุดบริการและทำให้เกิดข้อผิดพลาดแอปพลิเคชันไม่ตอบสนอง (ANR)

บริการแบบสั้นทำงานนานเกินไปจนทำให้เกิด ANR

บริการที่ทำงานอยู่เบื้องหน้าซึ่งใช้ประเภทบริการสั้นต้องดำเนินการให้เสร็จอย่างรวดเร็วภายในเวลาประมาณ 3 นาที เมื่อหมดเวลา ระบบจะเรียกใช้เมธอด Service.onTimeout(int,int) ของบริการ บริการมีเวลา 2-3 วินาทีในการโทรหา stopSelf() หากบริการไม่หยุดทำงานเอง ระบบจะทริกเกอร์ข้อผิดพลาด "แอปพลิเคชันไม่ตอบสนอง"

วิเคราะห์:

หาก ANR เกิดจากบริการที่ทำงานอยู่เบื้องหน้าไม่หยุดทำงาน ระบบจะแสดงข้อยกเว้นภายใน คุณสามารถยืนยันได้ว่าปัญหานี้เกิดขึ้นจริงโดยการตรวจสอบรายงาน ANR หากเป็นกรณีนี้ รายงานจะมีข้อความต่อไปนี้

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type FOREGROUND_SERVICE_TYPE_SHORT_SERVICE did not stop within its timeout:
[component name]"

วิธีแก้ไข

ตรวจสอบว่าบริการที่ทำงานอยู่เบื้องหน้าซึ่งมีเวลาจำกัดทั้งหมดทำงานเสร็จและเรียกใช้ stopForeground(int) ภายในเวลาที่ระบบจำกัดไว้

ให้ใช้ Service.onTimeout(int,int) ในบริการที่ทำงานอยู่เบื้องหน้า ตรวจสอบว่าการติดตั้งใช้งานเมธอดดังกล่าวเรียกใช้ stopSelf() ทันที

ข้อยกเว้นสำหรับบริการที่ทำงานอยู่เบื้องหน้า

ส่วนนี้จะอธิบายปัญหาเกี่ยวกับบริการที่ทำงานอยู่เบื้องหน้าหลายประการที่อาจทำให้ระบบแสดงข้อยกเว้น หากแอปไม่ตรวจจับข้อยกเว้น ผู้ใช้จะเห็นกล่องโต้ตอบที่แจ้งว่าแอปหยุดทำงาน

ในบางกรณี ระบบจะแสดงข้อยกเว้นภายใน ในกรณีดังกล่าว คุณสามารถดูข้อยกเว้นได้โดยดูในสแต็กเทรซ และตรวจสอบ Logcat เพื่อดูข้อมูลข้อผิดพลาดโดยละเอียดเพิ่มเติม

ข้อยกเว้นภายใน: เกินระยะหมดเวลา

ระบบจะจำกัดระยะเวลาที่บริการที่ทำงานอยู่เบื้องหน้าสำหรับการซิงค์ข้อมูลและการประมวลผลสื่อจะทำงานได้ขณะที่แอปทำงานอยู่เบื้องหลัง หากบริการเกินขีดจำกัดดังกล่าว ระบบจะเรียกใช้เมธอด Service.onTimeout(int,int) ของบริการ บริการมีเวลา 2-3 วินาทีในการเรียกใช้ stopSelf() หากบริการไม่หยุดทำงานเอง ระบบจะสร้าง RemoteServiceException ภายในซึ่งทำให้แอปขัดข้อง

วิเคราะห์:

คุณสามารถดูว่าข้อยกเว้นคืออะไรได้โดยดูในสแต็กเทรซ และตรวจสอบ Logcat เพื่อดูข้อมูลข้อผิดพลาดโดยละเอียดเพิ่มเติม ในกรณีนี้ Logcat จะมีข้อความแสดงข้อผิดพลาดต่อไปนี้

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type [service type] did not stop within its timeout: [component name]"

วิธีแก้ไข

ตรวจสอบว่าบริการที่ทำงานอยู่เบื้องหน้าซึ่งมีเวลาจำกัดทั้งหมดทำงานเสร็จและเรียกใช้ stopForeground(int) ภายในขีดจำกัดเวลาของระบบ

ให้ใช้ Service.onTimeout(int,int) ในบริการที่ทำงานอยู่เบื้องหน้า ตรวจสอบว่าการติดตั้งใช้งานเมธอดดังกล่าวเรียกใช้ stopSelf() ทันที

ข้อยกเว้นภายใน: ForegroundServiceDidNotStartInTimeException

เมื่อคุณเปิดใช้บริการโดยเรียกใช้ context.startForegroundService() บริการดังกล่าวจะมีเวลา 2-3 วินาทีในการโปรโมตตัวเองเป็นบริการที่ทำงานอยู่เบื้องหน้าโดยเรียกใช้ ServiceCompat.startForeground() หากบริการไม่ดำเนินการดังกล่าว ระบบจะแสดงข้อผิดพลาดภายใน ForegroundServiceDidNotStartInTimeException

วิเคราะห์:

คุณสามารถดูว่าข้อยกเว้นคืออะไรได้โดยดูในสแต็กเทรซ และตรวจสอบ Logcat เพื่อดูข้อมูลข้อผิดพลาดโดยละเอียดเพิ่มเติม ในกรณีนี้ Logcat จะมีข้อความแสดงข้อผิดพลาดต่อไปนี้

android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException:
Context.startForegroundService() did not then call Service.startForeground()

วิธีแก้ไข

ตรวจสอบว่าบริการที่ทำงานอยู่เบื้องหน้าที่สร้างขึ้นใหม่ทั้งหมดเรียกใช้ ServiceCompat.startForeground() ภายในไม่กี่วินาที

WorkManager:

คุณอาจเห็นข้อยกเว้นนี้กับ Worker WorkManager ที่เรียกใช้บริการที่ทำงานอยู่เบื้องหน้า (เรียก setForegound หรือ setForegroundAsync) เมื่อวงจรของ Worker ที่ทำงานอยู่เบื้องหน้า 2 รายการทับซ้อนกันเนื่องจาก Worker รายหนึ่งพยายามเริ่มบริการที่ทำงานอยู่เบื้องหน้าขณะที่บริการที่ทำงานอยู่เบื้องหน้าซึ่งทำงานอยู่ก่อนหน้านี้พยายามปิดตัวลง การขัดข้องนี้จะมาพร้อมกับบันทึกต่อไปนี้

Re-initializing SystemForegroundService after a request to shut-down

การแก้ไขข้อขัดข้องนี้เปิดตัวใน WorkManager เวอร์ชัน 2.10.5

หากแอปพบข้อยกเว้นนี้ ให้อัปเดต WorkManager เป็นเวอร์ชันล่าสุดและรายงานปัญหาที่ยังคงอยู่ไปยังIssue Trackerของ WorkManager

ForegroundServiceStartNotAllowedException

ข้อผิดพลาด:

ระบบจะแสดง ForegroundServiceStartNotAllowedException

สาเหตุ:

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

ตั้งแต่ Android 12 (ระดับ API 31) เป็นต้นไป แอปไม่ได้รับอนุญาตให้เริ่มบริการที่ทำงานอยู่เบื้องหน้าขณะที่แอปทำงานอยู่ในเบื้องหลัง ยกเว้นในบางกรณีที่ได้รับการยกเว้น หากคุณพยายามเริ่มบริการที่ทำงานอยู่เบื้องหน้าจากเบื้องหลังและไม่เป็นไปตามข้อกำหนดของการยกเว้นข้อใดข้อหนึ่ง ระบบจะแสดง ForegroundServiceStartNotAllowedException นอกจากนี้ ระบบจะดำเนินการดังกล่าวหากคุณไม่มีคุณสมบัติตรงตามข้อกำหนดของการยกเว้น

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

นอกจากนี้ การยกเว้นบางรายการยังมีระยะเวลาที่จำกัด ตัวอย่างเช่น จะมีการยกเว้นสั้นๆ หากแอปของคุณเปิดบริการที่ทำงานอยู่เบื้องหน้าเพื่อตอบสนองต่อข้อความ FCM ที่มีความสำคัญสูง หากคุณไม่เปิดตัวบริการเร็วพอ คุณจะได้รับ ForegroundServiceStartNotAllowedException

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

วิธีแก้ไข

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

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

SecurityException

ข้อผิดพลาด:

ระบบจะแสดงข้อผิดพลาด SecurityException

สาเหตุ:

แอปของคุณพยายามเปิดบริการที่ทำงานอยู่เบื้องหน้าโดยไม่มีสิทธิ์ที่จำเป็น

  • หากแอปกำหนดเป้าหมายเป็น Android 9 (ระดับ API 28) ขึ้นไป แอปต้องมีสิทธิ์ FOREGROUND_SERVICE เพื่อเปิดบริการที่ทำงานอยู่เบื้องหน้า
  • หากแอปกำหนดเป้าหมายเป็น Android 14 (ระดับ API 34) ขึ้นไป แอปต้องเป็นไปตามข้อกำหนดเบื้องต้นทั้งหมดสำหรับประเภทบริการที่ทำงานอยู่เบื้องหน้า ข้อกำหนดเบื้องต้นเหล่านี้มีรายละเอียดอยู่ในเอกสารประกอบเกี่ยวกับประเภทบริการที่ทำงานอยู่เบื้องหน้า โดยเฉพาะอย่างยิ่ง โปรดคำนึงถึงข้อกำหนดต่อไปนี้
    • บริการที่ทำงานอยู่เบื้องหน้าหลายประเภทต้องใช้สิทธิ์รันไทม์ที่เฉพาะเจาะจง ตัวอย่างเช่น บริการที่ทำงานอยู่เบื้องหน้าสำหรับการรับส่งข้อความระยะไกลต้องมีสิทธิ์ FOREGROUND_SERVICE_REMOTE_MESSAGING
  • ในหลายกรณี จะมีข้อจำกัดเพิ่มเติมขณะใช้งานเกี่ยวกับสิทธิ์ที่จำเป็นสำหรับบริการที่ทำงานอยู่เบื้องหน้าบางประเภท สิทธิ์เหล่านี้จะมอบให้แก่แอปขณะที่แอปทำงานอยู่เบื้องหน้าเท่านั้น (ยกเว้นในบางกรณี) ซึ่งหมายความว่าแม้ว่าแอปของคุณจะขอและได้รับสิทธิ์อย่างใดอย่างหนึ่งเหล่านี้แล้ว แต่หากแอปพยายามเปิดบริการที่ทำงานอยู่เบื้องหน้าขณะที่แอปอยู่ในเบื้องหลัง ระบบจะแสดง SecurityException แม้ว่าแอปจะได้รับการยกเว้นให้เริ่มบริการที่ทำงานอยู่เบื้องหน้าจากเบื้องหลังก็ตาม ดูข้อมูลเพิ่มเติมได้ที่ข้อจำกัดในการเริ่มบริการที่ทำงานอยู่เบื้องหน้าซึ่งต้องใช้สิทธิ์ขณะใช้งาน
    • คุณอาจได้รับ SecurityException หากขอสิทธิ์ที่จำเป็นแต่เริ่มบริการที่ทำงานอยู่เบื้องหน้าก่อนที่จะยืนยันว่าได้รับสิทธิ์ที่จำเป็นแล้ว

วิธีแก้ไข

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