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

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

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

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

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

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

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

  • โค้ดบริการที่ทำงานอยู่เบื้องหน้าที่เคยทำงานได้ดี ตอนนี้กลับล้มเหลว
  • คุณเพิ่งเริ่มทดสอบในการเผยแพร่แพลตฟอร์ม 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() ภายในเวลา 2-3 วินาที

WorkManager:

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

Re-initializing SystemForegroundService after a request to shut-down

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

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

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 หากขอสิทธิ์ที่จำเป็นแล้ว แต่เริ่มบริการที่ทำงานอยู่เบื้องหน้าก่อนที่จะยืนยันว่าได้รับสิทธิ์ที่จำเป็นแล้ว

การแก้ไข:

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