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

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

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

ข้อจำกัดที่เริ่มต้นโดยผู้ใช้

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

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

  1. Wake Lock มากเกินไป: Wake Lock บางส่วนค้างไว้เป็นเวลา 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 แล้ว แต่ ConnectivityManager API ให้วิธีการที่มีประสิทธิภาพมากกว่าในการขอให้ติดต่อกลับเมื่อเครือข่ายที่ระบุเท่านั้น ตรงตามเงื่อนไข

ออบเจ็กต์ NetworkRequest กำหนดพารามิเตอร์ของ Callback ของเครือข่ายใน ข้อกำหนดของ NetworkCapabilities คุณสร้างออบเจ็กต์ NetworkRequest รายการ กับชั้นเรียน NetworkRequest.Builder registerNetworkCallback จากนั้นส่งออบเจ็กต์ NetworkRequest ไปยังระบบ เมื่อเครือข่าย ตรงตามเงื่อนไข แอปจะได้รับ Callback เพื่อดำเนินการ ได้กำหนดเมธอด 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()
    }
}

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

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