กระบวนการเบื้องหลังอาจใช้หน่วยความจำและแบตเตอรี่มาก ตัวอย่างเช่น การกระจายข้อมูลแบบไม่เจาะจงปลายทางอาจเริ่มกระบวนการเบื้องหลังหลายรายการที่ลงทะเบียนเพื่อรอรับข้อมูล แม้ว่ากระบวนการเหล่านั้นอาจไม่ได้ทำงานมากนักก็ตาม ซึ่งอาจส่งผลกระทบอย่างมากต่อทั้งประสิทธิภาพของอุปกรณ์และประสบการณ์ของผู้ใช้
โปรดตรวจสอบว่าคุณใช้ API ที่เหมาะสมสำหรับงานที่ทำงานอยู่เบื้องหลังเพื่อหลีกเลี่ยงข้อจำกัดของระบบ เอกสารประกอบภาพรวมงานที่ทำงานอยู่เบื้องหลังจะช่วยคุณเลือก API ที่เหมาะกับความต้องการ
ข้อจำกัดที่ผู้ใช้เริ่มต้น
หากแอปแสดงลักษณะการทำงานที่ไม่ถูกต้องบางอย่างตามที่อธิบายไว้ใน Android Vitals ระบบจะแจ้งให้ผู้ใช้จำกัดสิทธิ์เข้าถึงทรัพยากรระบบของแอปนั้น
หากระบบสังเกตเห็นว่าแอปใช้ทรัพยากรมากเกินไป ระบบจะแจ้งเตือนผู้ใช้และให้ตัวเลือกแก่ผู้ใช้ในการจำกัดการทำงานของแอป ลักษณะการทำงานที่อาจทำให้เกิดการแจ้งเตือนมีดังนี้
- Wake Lock มากเกินไป: Wake Lock บางส่วน 1 รายการที่ทำงานเป็นเวลา 1 ชั่วโมงเมื่อหน้าจอปิดอยู่
- บริการที่ทำงานอยู่เบื้องหลังมากเกินไป: หากแอปกำหนดเป้าหมายเป็น API ระดับต่ำกว่า 26 และมีบริการที่ทำงานอยู่เบื้องหลังมากเกินไป
ข้อจำกัดที่แน่นอนที่กำหนดจะขึ้นอยู่กับผู้ผลิตอุปกรณ์ ตัวอย่างเช่น ในบิลด์ AOSP แอปที่ถูกจำกัดจะไม่สามารถเรียกใช้งาน ทริกเกอร์การปลุก หรือใช้เครือข่ายได้ ยกเว้นเมื่อแอปทำงานอยู่เบื้องหน้า
ข้อจำกัดในการรับการออกอากาศกิจกรรมเครือข่าย
แอปจะไม่ได้รับการออกอากาศ CONNECTIVITY_ACTION หากลงทะเบียนเพื่อรับการออกอากาศในไฟล์ Manifest และกระบวนการที่ขึ้นอยู่กับการออกอากาศนี้จะไม่เริ่มทำงาน ซึ่งอาจก่อให้เกิดปัญหากับแอปที่ต้องการฟังการเปลี่ยนแปลงของเครือข่ายหรือทำกิจกรรมเครือข่ายจำนวนมากเมื่ออุปกรณ์เชื่อมต่อกับเครือข่ายที่ไม่มีการวัดปริมาณอินเทอร์เน็ต เฟรมเวิร์ก Android มีโซลูชันหลายอย่างที่ช่วยหลีกเลี่ยงข้อจำกัดนี้อยู่แล้ว แต่การเลือกโซลูชันที่เหมาะสมจะขึ้นอยู่กับสิ่งที่คุณต้องการให้แอปทำสำเร็จ
กำหนดเวลางานในการเชื่อมต่อที่ไม่มีการวัดปริมาณอินเทอร์เน็ต
เมื่อสร้างWorkRequest ให้เพิ่มNetworkType.UNMETERED Constraint
fun scheduleWork(context: Context) { val workManager = WorkManager.getInstance(context) val workRequest = OneTimeWorkRequestBuilder<MyWorker>() .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .build() ) .build() workManager.enqueue(workRequest) }
เมื่อเป็นไปตามเงื่อนไขสำหรับงาน แอปจะได้รับ Callback เพื่อเรียกใช้เมธอด doWork() ในคลาส Worker ที่ระบุ
ตรวจสอบการเชื่อมต่อเครือข่ายขณะที่แอปทำงานอยู่
แอปที่ทำงานอยู่จะยังคงฟัง CONNECTIVITY_CHANGE ได้ด้วย BroadcastReceiver ที่ลงทะเบียนไว้ อย่างไรก็ตาม ConnectivityManager API มีวิธีที่มีประสิทธิภาพมากกว่าในการขอ Callback เฉพาะเมื่อเป็นไปตามเงื่อนไขเครือข่ายที่ระบุ
ออบเจ็กต์ NetworkRequest จะกำหนดพารามิเตอร์ของ Callback ของเครือข่ายในแง่ของ NetworkCapabilities คุณสร้างออบเจ็กต์ NetworkRequest ด้วยคลาส NetworkRequest.Builder registerNetworkCallback
จากนั้นส่งออบเจ็กต์ NetworkRequest ไปยังระบบ เมื่อเป็นไปตามเงื่อนไขของเครือข่าย แอปจะได้รับการเรียกกลับเพื่อเรียกใช้เมธอด onAvailable() ที่กำหนดไว้ในคลาส ConnectivityManager.NetworkCallback
แอปจะยังคงได้รับ Callback ต่อไปจนกว่าแอปจะออกหรือเรียกใช้ unregisterNetworkCallback()
ข้อจำกัดในการรับการออกอากาศรูปภาพและวิดีโอ
แอปไม่สามารถส่งหรือรับการออกอากาศ ACTION_NEW_PICTURE หรือ ACTION_NEW_VIDEO ข้อจำกัดนี้ช่วยลดผลกระทบต่อประสิทธิภาพและประสบการณ์ของผู้ใช้เมื่อต้องปลุกแอปหลายแอปเพื่อประมวลผลรูปภาพหรือวิดีโอใหม่
ระบุว่าหน่วยงานด้านเนื้อหาใดเป็นผู้ทริกเกอร์การดำเนินการ
WorkerParameters ช่วยให้แอปได้รับข้อมูลที่เป็นประโยชน์เกี่ยวกับหน่วยงานด้านเนื้อหาและ URI ที่ทริกเกอร์งาน ดังนี้
List<Uri> getTriggeredContentUris()
แสดงรายการ URI ที่ทริกเกอร์งาน ข้อมูลนี้จะว่างเปล่าหากไม่มี URI ที่ทริกเกอร์งาน (เช่น งานถูกทริกเกอร์เนื่องจากถึงกำหนดเวลาหรือเหตุผลอื่นๆ) หรือจำนวน URI ที่เปลี่ยนแปลงมีมากกว่า 50 รายการ
List<String> getTriggeredContentAuthorities()
แสดงรายการสตริงของหน่วยงานด้านเนื้อหาที่ทริกเกอร์งาน หากรายการที่แสดงผลไม่ว่างเปล่า ให้ใช้ getTriggeredContentUris() เพื่อดึงรายละเอียดว่า URI ใดมีการเปลี่ยนแปลง
โค้ดตัวอย่างต่อไปนี้จะลบล้างเมธอด CoroutineWorker.doWork() และบันทึกหน่วยงานด้านเนื้อหาและ URI ที่ทริกเกอร์งาน
class MyWorker( appContext: Context, private val params: WorkerParameters ) : CoroutineWorker(appContext, params) { override suspend fun doWork(): Result { StringBuilder().apply { append("Media content has changed:\n") params.triggeredContentAuthorities .takeIf { it.isNotEmpty() } ?.let { authorities -> append("Authorities: ${authorities.joinToString(", ")}\n") append(params.triggeredContentUris.joinToString("\n")) } ?: append("(No content)") Log.i(TAG, toString()) } return Result.success() } }
ทดสอบแอปภายใต้ข้อจำกัดของระบบ
การเพิ่มประสิทธิภาพแอปให้ทำงานบนอุปกรณ์ที่มีหน่วยความจำต่ำหรือในสภาวะที่มีหน่วยความจำต่ำจะช่วยปรับปรุงประสิทธิภาพและประสบการณ์ของผู้ใช้ได้ การนำทรัพยากร Dependency ในบริการที่ทำงานอยู่เบื้องหลังและ Broadcast Receiver แบบไม่เจาะจงปลายทางที่ลงทะเบียนในไฟล์ Manifest ออกจะช่วยให้แอปทำงานได้ดีขึ้นในอุปกรณ์ดังกล่าว เราขอแนะนำให้คุณเพิ่มประสิทธิภาพแอปให้ทำงานโดยไม่ต้องใช้กระบวนการเบื้องหลังเหล่านี้เลย
คำสั่ง Android Debug Bridge (ADB) เพิ่มเติมบางคำสั่งจะช่วยคุณทดสอบลักษณะการทำงานของแอปเมื่อปิดใช้กระบวนการเบื้องหลังเหล่านั้นได้
หากต้องการจำลองสภาวะที่การกระจายข้อมูลแบบไม่เจาะจงปลายทางและบริการที่ทำงานอยู่เบื้องหลังไม่พร้อมใช้งาน ให้ป้อนคำสั่งต่อไปนี้
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignoreหากต้องการเปิดใช้การกระจายข้อมูลแบบไม่เจาะจงปลายทางและบริการที่ทำงานอยู่เบื้องหลังอีกครั้ง ให้ป้อนคำสั่งต่อไปนี้
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
เพิ่มประสิทธิภาพแอปให้ดียิ่งขึ้น
ดูวิธีอื่นๆ ที่ดีในการเพิ่มประสิทธิภาพลักษณะการทำงานของงานที่ทำงานอยู่เบื้องหลังได้ในเอกสารประกอบเพิ่มประสิทธิภาพการใช้แบตเตอรี่สำหรับ API การกำหนดเวลางาน