ข้อจำกัดของระบบเกี่ยวกับงานในเบื้องหลัง

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

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

ข้อจำกัดที่ผู้ใช้เป็นผู้กำหนด

หากแอปแสดงลักษณะการทำงานที่ไม่ดีบางอย่างที่อธิบายไว้ใน Android vitals, ระบบจะแจ้งให้ผู้ใช้จำกัดการเข้าถึงทรัพยากรระบบของแอปนั้น

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

  1. Wake Lock มากเกินไป: Wake Lock บางส่วน 1 รายการที่ทำงานเป็นเวลา 1 ชั่วโมงเมื่อหน้าจอ ปิดอยู่
  2. บริการเบื้องหลังมากเกินไป: หากแอปกำหนดเป้าหมายเป็น API ระดับต่ำกว่า 26 และมีบริการเบื้องหลังมากเกินไป

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

ข้อจำกัดในการรับการออกอากาศกิจกรรมเครือข่าย

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

กำหนดเวลาให้ทำงานเมื่อมีการเชื่อมต่อที่ไม่มีการวัดปริมาณอินเทอร์เน็ต

เมื่อสร้าง WorkRequest ให้เพิ่ม Constraint ของ NetworkType.UNMETERED

fun scheduleWork(context: Context) {
    val workManager = WorkManager.getInstance(context)
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
       .setConstraints(
           Constraints.Builder()
               .setRequiredNetworkType(NetworkType.UNMETERED)
               .build()
           )
       .build()

    workManager.enqueue(workRequest)
}

เมื่อตรงตามเงื่อนไขของงาน แอปจะได้รับการเรียกกลับเพื่อเรียกใช้ เมธอด doWork() ในคลาส Worker ที่ระบุ

ตรวจสอบการเชื่อมต่อเครือข่ายขณะที่แอปกำลังทำงาน

แอปที่กำลังทำงานจะยังคงรับฟัง CONNECTIVITY_CHANGE ได้ด้วย BroadcastReceiver ที่ลงทะเบียนไว้ อย่างไรก็ตาม API ของ ConnectivityManager มีวิธีที่เชื่อถือได้มากกว่าในการขอการเรียกกลับเมื่อตรงตามเงื่อนไขเครือข่ายที่ระบุเท่านั้น

NetworkRequest ออบเจ็กต์จะกำหนดพารามิเตอร์ของการเรียกกลับเครือข่ายใน แง่ของ NetworkCapabilities คุณสร้างออบเจ็กต์ NetworkRequest ด้วยคลาส NetworkRequest.Builder registerNetworkCallback จากนั้นจะส่งออบเจ็กต์ NetworkRequest ไปยังระบบ เมื่อตรงตามเงื่อนไขเครือข่าย แอปจะได้รับการเรียกกลับเพื่อเรียกใช้เมธอด onAvailable() ที่กำหนดไว้ในคลาส ConnectivityManager.NetworkCallback

แอปจะยังคงได้รับการเรียกกลับจนกว่าแอปจะออกหรือเรียกใช้ 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,
    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()
    }
}

ทดสอบแอปภายใต้ข้อจำกัดของระบบ

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