ฮาวทู

การบังคับใช้คุณภาพทางเทคนิคของแบตเตอรี่มาถึงแล้ว: วิธีเพิ่มประสิทธิภาพกรณีการใช้งาน Wake Lock ทั่วไป

ใช้เวลาอ่าน 8 นาที
Alice Yuan
วิศวกรนักพัฒนาซอฟต์แวร์สัมพันธ์

Google ทราบดีว่าการใช้แบตเตอรี่หมดเร็วเป็นสิ่งที่ผู้ใช้ Android เป็นที่หนึ่งในใจ จึงได้ดำเนินการอย่างจริงจังเพื่อช่วยให้นักพัฒนาแอปสร้างแอปที่ประหยัดพลังงานมากขึ้น เมื่อวันที่ 1 มีนาคม 2026 Google Play Store ได้เริ่มเปิดตัวการจัดการคุณภาพทางเทคนิคของ Wake Lock เพื่อปรับปรุงปัญหาแบตเตอรี่หมดเร็ว เราจะทยอยใช้การจัดการนี้กับแอปที่ได้รับผลกระทบในอีกไม่กี่สัปดาห์ข้างหน้า แอปที่เกินเกณฑ์ "Wake Lock บางส่วนมากเกินไป" ใน Android Vitals อย่างต่อเนื่องอาจได้รับผลกระทบที่จับต้องได้ต่อการแสดงข้อมูลสินค้าใน Store ซึ่งรวมถึงคำเตือนในข้อมูลสินค้าใน Store และการยกเว้นจากแพลตฟอร์มการค้นพบ เช่น คำแนะนำ

appDetails.png

ผู้ใช้อาจเห็นคำเตือนในข้อมูลสินค้าใน Store หากแอปของคุณมีลักษณะการทำงานที่ไม่ถูกต้องเกินเกณฑ์ 

โครงการนี้ได้ยกระดับประสิทธิภาพแบตเตอรี่ให้เป็นเมตริกหลักที่สำคัญควบคู่ไปกับเมตริกความเสถียร เช่น ข้อขัดข้องและ ANR "เกณฑ์ลักษณะการทำงานที่ไม่ถูกต้อง" หมายถึงการถือ Wake Lock บางส่วนที่ไม่อยู่ในข้อยกเว้นเป็นเวลาอย่างน้อย 2 ชั่วโมงโดยเฉลี่ยขณะที่หน้าจอปิดอยู่ในเซสชันของผู้ใช้มากกว่า 5% ในช่วง 28 วันที่ผ่านมา Wake Lock จะได้รับการยกเว้นหากเป็น Wake Lock ที่ระบบถือครองซึ่งให้ประโยชน์ที่ชัดเจนแก่ผู้ใช้และไม่สามารถเพิ่มประสิทธิภาพได้อีก เช่น การเล่นเสียง การเข้าถึงตำแหน่ง หรือการโอนข้อมูลที่ผู้ใช้เริ่มต้น ดูคำจำกัดความแบบเต็มของ Wake Lock ที่มากเกินไปได้ในเอกสารประกอบของ Android Vitals

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

การใช้บริการที่ทำงานอยู่เบื้องหน้าเทียบกับการล็อกการปลุกบางส่วน

เรามักเห็นนักพัฒนาแอปประสบปัญหาในการทำความเข้าใจความแตกต่างระหว่างแนวคิด 2 อย่างเมื่อทำการดำเนินการในเบื้องหลัง ได้แก่ บริการที่ทำงานอยู่เบื้องหน้าและ Wake Lock บางส่วน

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

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

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

ไลบรารีของบุคคลที่สามที่ได้รับ Wake Lock

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

  • ตรวจสอบ Android Vitals: ค้นหาชื่อที่แน่นอนของ Wake Lock ที่ละเมิดในแดชบอร์ด Wake Lock บางส่วนที่มากเกินไป ตรวจสอบเพื่อเปรียบเทียบชื่อนี้กับคำแนะนำในหัวข้อระบุ Wake Lock ที่สร้างโดย API อื่นๆ เพื่อดูว่าสร้างโดย API ของระบบที่รู้จักหรือไลบรารี Jetpack หรือไม่ หากเป็นเช่นนั้น คุณอาจต้องเพิ่มประสิทธิภาพการใช้งาน API และดูคำแนะนำที่แนะนำ
  • บันทึกการติดตามระบบ: หากระบุ Wake Lock ได้ยาก ให้จำลองปัญหา Wake Lock ในเครื่องโดยใช้การติดตามระบบ แล้วตรวจสอบด้วย UI ของ Perfetto ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีดำเนินการนี้ได้ในส่วนการแก้ไขข้อบกพร่องของ Wake Lock ประเภทอื่นๆ ที่มากเกินไป ของบล็อกโพสต์นี้
  • ประเมินทางเลือก: หากไลบรารีของบุคคลที่สามที่ไม่มีประสิทธิภาพเป็นสาเหตุและกำหนดค่าให้คำนึงถึงอายุการใช้งานแบตเตอรี่ไม่ได้ ให้พิจารณาสื่อสารปัญหาดังกล่าวกับเจ้าของ SDK, หา SDK ทางเลือก หรือสร้างฟังก์ชันการทำงานภายใน

สถานการณ์ที่พบบ่อยเกี่ยวกับ Wake Lock

ด้านล่างนี้คือรายละเอียดของกรณีการใช้งานเฉพาะบางส่วนที่เราได้ตรวจสอบ พร้อมเส้นทางที่แนะนำในการเพิ่มประสิทธิภาพการใช้งาน Wake Lock

การอัปโหลดหรือดาวน์โหลดที่ผู้ใช้ดำเนินการ

ตัวอย่างกรณีการใช้งาน 

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

วิธีลดการทำงานขณะล็อก 

  • อย่าใช้ Wake Lock ด้วยตนเอง แต่ให้ใช้ API การโอนข้อมูลที่เริ่มต้นโดยผู้ใช้ (UIDT) แทน นี่คือเส้นทางที่กำหนดไว้สำหรับงานการโอนข้อมูลที่ใช้เวลานานซึ่งผู้ใช้เป็นผู้เริ่ม และได้รับการยกเว้นจากการคำนวณ Wake Lock ที่มากเกินไป

การซิงค์ในเบื้องหลังแบบครั้งเดียวหรือตามระยะเวลา

ตัวอย่างกรณีการใช้งาน 

  • แอปจะทำการซิงค์ในเบื้องหลังเป็นระยะเพื่อดึงข้อมูลสำหรับการเข้าถึงแบบออฟไลน์ 
  • แอปเครื่องนับก้าวที่ดึงข้อมูลจำนวนก้าวเป็นระยะๆ

วิธีลดการทำงานขณะล็อก 

  • อย่าใช้ Wake Lock ด้วยตนเอง ใช้ WorkManager ที่กำหนดค่าสำหรับงานแบบครั้งเดียวหรืองานเป็นระยะ WorkManager เคารพสถานะของระบบด้วยการจัดกลุ่มงาน และมีช่วงเวลาเป็นระยะขั้นต่ำ (15 นาที) ซึ่งโดยทั่วไปเพียงพอสำหรับการอัปเดตในเบื้องหลัง 
  • หากพบว่า Wake Lock ที่สร้างโดย WorkManager หรือ JobScheduler มีการใช้งาน Wake Lock สูง อาจเป็นเพราะคุณกำหนดค่า Worker ไม่ถูกต้องเพื่อให้ทำงานไม่เสร็จในบางสถานการณ์ ลองวิเคราะห์เหตุผลที่หยุดการทำงานของผู้ปฏิบัติงาน โดยเฉพาะหากคุณเห็นว่ามี STOP_REASON_TIMEOUT เกิดขึ้นบ่อย 
workManager.getWorkInfoByIdFlow(syncWorker.id)
  .collect { workInfo ->
      if (workInfo != null) {
        val stopReason = workInfo.stopReason
        logStopReason(syncWorker.id, stopReason)
      }
  }
  • นอกเหนือจากการบันทึกเหตุผลที่ทำให้ Worker หยุดทำงานแล้ว โปรดดูเอกสารประกอบเกี่ยวกับการแก้ไขข้อบกพร่องของ Worker นอกจากนี้ ให้พิจารณารวบรวมและวิเคราะห์การติดตามระบบ เพื่อทำความเข้าใจว่าเมื่อใดที่ได้และปล่อย Wake Lock
  • สุดท้ายนี้ โปรดดูกรณีศึกษาของ WHOOP ซึ่งสามารถค้นพบปัญหาเกี่ยวกับการกำหนดค่าของ Worker และลดผลกระทบของ Wake Lock ได้อย่างมาก

การสื่อสารผ่านบลูทูธ

ตัวอย่างกรณีการใช้งาน 

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

วิธีลดการทำงานขณะล็อก 

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

ติดตามตำแหน่ง

ตัวอย่างกรณีการใช้งาน 

  • แอปฟิตเนสที่แคชข้อมูลตำแหน่งเพื่ออัปโหลดในภายหลัง เช่น การวางแผนเส้นทางการวิ่ง
  • แอปนำส่งอาหารที่ดึงข้อมูลตำแหน่งด้วยความถี่สูงเพื่ออัปเดตความคืบหน้าของการนำส่งใน UI ของการแจ้งเตือนหรือวิดเจ็ต

วิธีลดการทำงานขณะล็อก 

  • โปรดอ่านคำแนะนำเพื่อเพิ่มประสิทธิภาพการใช้งานตำแหน่ง ลองใช้การหมดเวลา ใช้ประโยชน์จากการจัดกลุ่มคำขอตำแหน่ง หรือใช้การอัปเดตตำแหน่งแบบพาสซีฟเพื่อให้มั่นใจว่าแบตเตอรี่มีประสิทธิภาพ
  • เมื่อขอการอัปเดตตำแหน่งโดยใช้ FusedLocationProvider หรือ LocationManager API ระบบจะทริกเกอร์การปลุกอุปกรณ์โดยอัตโนมัติในระหว่างการเรียกกลับเหตุการณ์ตำแหน่ง Wake Lock ที่ระบบจัดการนี้จะได้รับการยกเว้นจากการคำนวณ Wake Lock บางส่วนที่มากเกินไป
  • หลีกเลี่ยงการรับ Wake Lock แบบต่อเนื่องแยกต่างหากสำหรับการแคชข้อมูลตำแหน่ง เนื่องจากเป็นการดำเนินการที่ซ้ำซ้อน แต่ให้เก็บเหตุการณ์ตำแหน่งไว้ในหน่วยความจำหรือพื้นที่เก็บข้อมูลในเครื่อง และใช้ WorkManager เพื่อประมวลผลเหตุการณ์เหล่านั้นเป็นระยะๆ
override fun onCreate(savedInstanceState: Bundle?) {
    locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult?) {
            locationResult ?: return
            // System wakes up CPU for short duration
            for (location in locationResult.locations){
                // Store data in memory to process at another time
            }
        }
    }
}

การตรวจสอบเซ็นเซอร์ความถี่สูง

ตัวอย่างกรณีการใช้งาน 

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

วิธีลดการทำงานขณะล็อก 

  • หากใช้ SensorManager ให้ลดการใช้งานเป็นช่วงเวลาเป็นระยะๆ และเฉพาะเมื่อผู้ใช้ให้สิทธิ์เข้าถึงอย่างชัดแจ้งผ่านการโต้ตอบ UI การตรวจสอบเซ็นเซอร์ที่มีความถี่สูงอาจทำให้แบตเตอรี่หมดเร็วเนื่องจากจำนวนการปลุกและการประมวลผลของ CPU ที่เกิดขึ้น
  • หากคุณติดตามจำนวนก้าวหรือระยะทางที่เดิน ให้ใช้ Recording API แทนการใช้ SensorManager หรือพิจารณาใช้ Health Connect เพื่อเข้าถึงจำนวนก้าวของอุปกรณ์ในอดีตและแบบรวมเพื่อบันทึกข้อมูลในลักษณะที่ประหยัดแบตเตอรี่
  • หากลงทะเบียนเซ็นเซอร์ด้วย SensorManager ให้ระบุ maxReportLatencyUs เป็น 30 วินาทีขึ้นไปเพื่อใช้ประโยชน์จากการจัดกลุ่มเซ็นเซอร์เพื่อลดความถี่ของการหยุดชะงักของ CPU เมื่ออุปกรณ์ตื่นขึ้นในภายหลังด้วยทริกเกอร์อื่น เช่น การโต้ตอบของผู้ใช้ การดึงข้อมูลตำแหน่ง หรือการทำงานที่กำหนดเวลาไว้ ระบบจะส่งข้อมูลเซ็นเซอร์ที่แคชไว้ทันที
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

sensorManager.registerListener(this,
                 accelerometer,
                 samplingPeriodUs, // How often to sample data
                 maxReportLatencyUs // Key for sensor batching 
              )
  • หากแอปต้องใช้ทั้งข้อมูลตำแหน่งและข้อมูลเซ็นเซอร์ ให้ซิงค์การดึงและการประมวลผลเหตุการณ์ของข้อมูลทั้ง 2 ประเภท การใช้ค่าเซ็นเซอร์ร่วมกับ Wake Lock แบบสั้นที่ระบบใช้สำหรับการอัปเดตตำแหน่งจะช่วยให้คุณไม่ต้องใช้ Wake Lock เพื่อให้ CPU ทำงานอยู่ ใช้ Worker หรือ Wake Lock ระยะสั้นเพื่อจัดการการอัปโหลดและการประมวลผลข้อมูลที่รวมกันนี้

การรับส่งข้อความระยะไกล

ตัวอย่างกรณีการใช้งาน 

  • แอปคู่หูสำหรับการตรวจสอบวิดีโอหรือเสียงที่ต้องตรวจสอบเหตุการณ์ที่เกิดขึ้นในอุปกรณ์ภายนอกซึ่งเชื่อมต่อโดยใช้เครือข่าย LAN
  • แอปส่งข้อความที่รักษาการเชื่อมต่อซ็อกเก็ตเครือข่ายกับแอปเวอร์ชันเดสก์ท็อป

วิธีลดการทำงานขณะล็อก 

  • หากประมวลผลเหตุการณ์เครือข่ายในฝั่งเซิร์ฟเวอร์ได้ ให้ใช้ FCM เพื่อรับข้อมูลในไคลเอ็นต์ คุณเลือกตั้งเวลาผู้ปฏิบัติงานแบบเร่งด่วนได้หากต้องประมวลผลข้อมูล FCM เพิ่มเติม 
  • หากต้องประมวลผลเหตุการณ์ในฝั่งไคลเอ็นต์ผ่านการเชื่อมต่อซ็อกเก็ต ก็ไม่จำเป็นต้องใช้ Wake Lock เพื่อฟังการขัดจังหวะของเหตุการณ์ เมื่อแพ็กเก็ตข้อมูลมาถึงวิทยุ Wi-Fi หรือเซลลูลาร์ ฮาร์ดแวร์วิทยุจะทริกเกอร์การหยุดชะงักของฮาร์ดแวร์ในรูปแบบของ Wake Lock ของเคอร์เนล จากนั้นคุณอาจเลือกกำหนดเวลาให้ Worker หรือรับ Wake Lock เพื่อประมวลผลข้อมูล
  • ตัวอย่างเช่น หากคุณใช้ ktor-network เพื่อฟังแพ็กเก็ตข้อมูลในซ็อกเก็ตเครือข่าย คุณควรขอ Wake Lock เฉพาะเมื่อมีการส่งแพ็กเก็ตไปยังไคลเอ็นต์และต้องประมวลผล
val readChannel = socket.openReadChannel()
while (!readChannel.isClosedForRead) {
    // CPU can safely sleep here while waiting for the next packet
    val packet = readChannel.readRemaining(1024) 
    if (!packet.isEmpty) {
         // Data Arrived: The system woke the CPU and we should keep it awake via manual wake lock (urgent) or scheduling a worker (non-urgent)
         performWorkWithWakeLock { 
              val data = packet.readBytes()
              // Additional logic to process data packets
         }
    }
}

สรุป

การนำโซลูชันที่แนะนำเหล่านี้ไปใช้กับกรณีการใช้งานทั่วไป เช่น การซิงค์ในเบื้องหลัง การติดตามตำแหน่ง การตรวจสอบเซ็นเซอร์ และการสื่อสารผ่านเครือข่าย จะช่วยให้นักพัฒนาแอปสามารถลดการใช้ Wake Lock ที่ไม่จำเป็นได้ หากต้องการเรียนรู้เพิ่มเติม โปรดอ่านบล็อกโพสต์ทางเทคนิคอื่นๆ หรือดูวิดีโอทางเทคนิคเกี่ยวกับวิธีค้นหาและแก้ไขข้อบกพร่องของ Wake Lock: เพิ่มประสิทธิภาพแบตเตอรี่ของแอปโดยใช้เมตริก Wake Lock ของ Android Vitals นอกจากนี้ โปรดอ่านเอกสารประกอบเกี่ยวกับ Wakelock ที่อัปเดตแล้ว โปรดแชร์ความคิดเห็นเพิ่มเติมเกี่ยวกับคำแนะนำของเราในแบบสำรวจความคิดเห็นเกี่ยวกับเอกสารประกอบ เพื่อช่วยเราปรับปรุงแหล่งข้อมูลทางเทคนิคต่อไป

เขียนโดย

อ่านต่อ