چگونه‌ها

اجرای قانون کیفیت فنی باتری از راه رسید: چگونه موارد استفاده رایج از قفل بیدارباش را بهینه کنیم

۸ دقیقه مطالعه
Alice Yuan
مهندس روابط توسعه‌دهنده

با توجه به اینکه تخلیه بیش از حد باتری برای کاربران اندروید از اهمیت بالایی برخوردار است، گوگل گام‌های مهمی را برای کمک به توسعه‌دهندگان در ساخت برنامه‌های کم‌مصرف‌تر برداشته است. در اول مارس ۲۰۲۶ ، فروشگاه گوگل پلی شروع به ارائه راهکارهای فنی قفل بیدارباش برای بهبود تخلیه باتری کرد. این راهکار به تدریج در هفته‌های بعدی برای برنامه‌های تحت تأثیر اعمال خواهد شد. برنامه‌هایی که به طور مداوم از آستانه "قفل بیدارباش جزئی بیش از حد" در داده‌های حیاتی اندروید عبور می‌کنند، ممکن است تأثیرات ملموسی بر حضورشان در فروشگاه، از جمله هشدارهایی در فهرست فروشگاه و حذف از سطوح کشف مانند توصیه‌ها، مشاهده کنند.

جزئیات برنامه.png

اگر برنامه شما از آستانه رفتار بد عبور کند، کاربران ممکن است در فهرست فروشگاه شما هشداری ببینند.

این ابتکار، بهره‌وری باتری را در کنار معیارهای پایداری مانند خرابی‌ها و ANRها به یک معیار حیاتی اصلی ارتقا داد. «آستانه رفتار بد» به صورت نگه داشتن قفل بیداری جزئیِ بدون معافیت به مدت حداقل دو ساعت به طور متوسط ​​در حالی که صفحه نمایش در بیش از ۵٪ از جلسات کاربر در ۲۸ روز گذشته خاموش بوده است، تعریف می‌شود. قفل بیداری در صورتی معاف می‌شود که قفل بیداریِ سیستمی باشد و مزایای واضحی را برای کاربر ارائه دهد که نمی‌توان آنها را بیشتر بهینه کرد، مانند پخش صدا، دسترسی به موقعیت مکانی یا انتقال داده به ابتکار کاربر. می‌توانید تعریف کامل قفل‌های بیداری بیش از حد را در مستندات Android Vitals ما مشاهده کنید.

به عنوان بخشی از ابتکار عمل مداوم ما برای بهبود عمر باتری در سراسر اکوسیستم اندروید، هزاران برنامه و نحوه استفاده آنها از قفل‌های بیداری جزئی را تجزیه و تحلیل کرده‌ایم. در حالی که قفل‌های بیداری گاهی اوقات ضروری هستند، اغلب شاهد هستیم که برنامه‌ها آنها را به طور ناکارآمد یا غیرضروری نگه می‌دارند، در حالی که راه‌حل‌های کارآمدتری وجود دارد. این وبلاگ به رایج‌ترین سناریوهایی که در آنها قفل‌های بیداری بیش از حد رخ می‌دهد و توصیه‌های ما برای بهینه‌سازی قفل‌های بیداری می‌پردازد. ما قبلاً موفقیت قابل اندازه‌گیری از شرکایی مانند WHOOP دیده‌ایم که از این توصیه‌ها برای بهینه‌سازی رفتار پس‌زمینه خود استفاده کرده‌اند.

استفاده از سرویس پیش‌زمینه در مقابل قفل‌های بیداری جزئی

ما اغلب شاهد بوده‌ایم که توسعه‌دهندگان هنگام انجام اجرای پس‌زمینه، برای درک تفاوت بین دو مفهوم مشکل دارند: سرویس پیش‌زمینه و قفل‌های بیداری جزئی.

یک سرویس پیش‌زمینه، یک API چرخه عمر است که به سیستم سیگنال می‌دهد که یک برنامه در حال انجام کاری است که کاربر متوجه آن می‌شود و نباید برای بازیابی حافظه از کار بیفتد، اما به طور خودکار مانع از به خواب رفتن CPU هنگام خاموش شدن صفحه نمی‌شود. در مقابل، قفل بیداری جزئی مکانیزمی است که به طور خاص برای فعال نگه داشتن CPU حتی در هنگام خاموش بودن صفحه طراحی شده است.

در حالی که یک سرویس پیش‌زمینه اغلب برای ادامه یک اقدام کاربر ضروری است، دریافت دستی قفل بیداری جزئی فقط در رابطه با یک سرویس پیش‌زمینه برای مدت زمان فعالیت CPU ضروری است. علاوه بر این، اگر از قبل از یک API استفاده می‌کنید که دستگاه را بیدار نگه می‌دارد، نیازی به استفاده از قفل بیداری ندارید.

برای اطمینان از اینکه درک کاملی از ابزاری که باید برای جلوگیری از دریافت قفل بیدارباش در مواقع غیرضروری استفاده کنید، دارید، به نمودار جریان در بخش «رابط برنامه‌نویسی کاربردی مناسب برای بیدار نگه داشتن دستگاه» مراجعه کنید.

کتابخانه‌های شخص ثالث که قفل‌های بیداری را به دست می‌آورند

معمولاً یک برنامه متوجه می‌شود که به دلیل قفل‌های بیداری بیش از حد که توسط یک SDK یا API سیستم شخص ثالث که از طرف آن عمل می‌کند، علامت‌گذاری شده است. برای شناسایی و رفع این قفل‌های بیداری، مراحل زیر را توصیه می‌کنیم:

  • بررسی موارد حیاتی اندروید: نام دقیق قفل بیداری مشکل‌دار را در داشبورد قفل‌های بیداری جزئی بیش از حد پیدا کنید. این نام را با راهنمای « شناسایی قفل‌های بیداری ایجاد شده توسط سایر APIها» مقایسه کنید تا ببینید آیا توسط یک API سیستم شناخته شده یا کتابخانه Jetpack ایجاد شده است یا خیر. در این صورت، ممکن است لازم باشد استفاده خود از API را بهینه کنید و می‌توانید به راهنمای توصیه شده مراجعه کنید.
  • ردیابی سیستم را ثبت کنید: اگر قفل بیداری به راحتی قابل شناسایی نیست، مشکل قفل بیداری را به صورت محلی با استفاده از ردیابی سیستم ایجاد کنید و آن را با رابط کاربری Perfetto بررسی کنید. می‌توانید در بخش اشکال‌زدایی انواع دیگر قفل‌های بیداری بیش از حد، اطلاعات بیشتری در مورد نحوه انجام این کار کسب کنید.   بخشی از این پست وبلاگ .
  • ارزیابی جایگزین‌ها: اگر یک کتابخانه شخص ثالث ناکارآمد مسئول است و نمی‌توان آن را طوری پیکربندی کرد که به عمر باتری توجه کند، در نظر داشته باشید که مشکل را با صاحبان SDK در میان بگذارید، یک SDK جایگزین پیدا کنید یا عملکرد آن را به صورت داخلی بسازید.

سناریوهای رایج قفل بیداری

در زیر، به تفصیل برخی از موارد استفاده خاصی که بررسی کرده‌ایم، به همراه مسیر پیشنهادی برای بهینه‌سازی پیاده‌سازی قفل بیدارباش شما، آورده شده است.

آپلود یا دانلود توسط کاربر آغاز می‌شود

موارد استفاده مثال:

  • برنامه‌های پخش ویدئو که در آن کاربر یک فایل حجیم را برای دسترسی آفلاین دانلود می‌کند.
  • برنامه‌های پشتیبان‌گیری رسانه‌ای که در آن‌ها کاربر از طریق اعلان، آپلود عکس‌های اخیر خود را آغاز می‌کند.

چگونه میزان قفل شدن صفحه نمایش را کاهش دهیم:

همگام‌سازی‌های پس‌زمینه یک‌باره یا دوره‌ای

موارد استفاده مثال:

  • یک برنامه همگام‌سازی‌های دوره‌ای در پس‌زمینه انجام می‌دهد تا داده‌ها را برای دسترسی آفلاین دریافت کند.
  • برنامه‌های گام‌شمار که تعداد گام‌ها را به صورت دوره‌ای دریافت می‌کنند.

چگونه میزان قفل شدن صفحه نمایش را کاهش دهیم:

  • قفل بیدارباش دستی تهیه نکنید. از WorkManager که برای کارهای یک‌باره یا دوره‌ای پیکربندی شده است استفاده کنید. WorkManager با دسته‌بندی وظایف، سلامت سیستم را حفظ می‌کند و حداقل فاصله زمانی دوره‌ای (۱۵ دقیقه) دارد که عموماً برای به‌روزرسانی‌های پس‌زمینه کافی است.
  • اگر متوجه شدید که wake lock های ایجاد شده توسط WorkManager یا JobScheduler استفاده بالایی از wake lock دارند، ممکن است به این دلیل باشد که worker خود را به اشتباه پیکربندی کرده‌اید تا در سناریوهای خاصی کار را تمام نکند. دلایل توقف 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 را بررسی کنید، جایی که آنها توانستند مشکلی را در پیکربندی کارگران خود کشف کنند و تأثیر قفل بیدارباش خود را به میزان قابل توجهی کاهش دهند.

ارتباط بلوتوث

موارد استفاده مثال:

  • برنامه دستگاه همراه، کاربر را ترغیب می‌کند تا دستگاه خارجی بلوتوث خود را جفت کند.
  • برنامه دستگاه همراه، رویدادهای سخت‌افزاری روی یک دستگاه خارجی و تغییرات قابل مشاهده توسط کاربر را در اعلان‌ها رصد می‌کند.
  • کاربر برنامه دستگاه همراه، انتقال فایل بین تلفن همراه و دستگاه بلوتوث را آغاز می‌کند.
  • برنامه دستگاه همراه، به‌روزرسانی‌های گاه‌به‌گاه میان‌افزار را از طریق بلوتوث برای یک دستگاه خارجی انجام می‌دهد.

چگونه میزان قفل شدن صفحه نمایش را کاهش دهیم:

  • برای جفت کردن دستگاه‌های بلوتوث، از جفت‌سازی دستگاه همراه استفاده کنید تا از قفل بیدارباش دستی هنگام جفت‌سازی بلوتوث جلوگیری شود.
  • مشورت کنید   برای آشنایی با نحوه برقراری ارتباط بلوتوثی در پس‌زمینه، از راهنمای ارتباط در پس‌زمینه استفاده کنید .
  • استفاده از WorkManager اغلب در صورتی کافی است که هیچ تأثیری بر کاربر در تأخیر ارتباط وجود نداشته باشد. اگر قفل بیدارباش دستی ضروری تشخیص داده شود، قفل بیدارباش را فقط برای مدت زمان فعالیت بلوتوث یا پردازش داده‌های فعالیت نگه دارید.

ردیابی موقعیت مکانی

موارد استفاده مثال:

  • برنامه‌های تناسب اندام که داده‌های موقعیت مکانی را برای آپلود بعدی مانند ترسیم مسیرهای دویدن، ذخیره می‌کنند
  • اپلیکیشن‌های تحویل غذا که داده‌های موقعیت مکانی را با فرکانس بالا دریافت می‌کنند تا پیشرفت تحویل را در یک رابط کاربری اعلان یا ویجت به‌روزرسانی کنند.

چگونه میزان قفل شدن صفحه نمایش را کاهش دهیم:

  • برای بهینه‌سازی استفاده از موقعیت مکانی ، به راهنمایی‌های ما مراجعه کنید. برای اطمینان از بهره‌وری باتری، پیاده‌سازی وقفه‌های زمانی، استفاده از دسته‌بندی درخواست‌های موقعیت مکانی یا استفاده از به‌روزرسانی‌های غیرفعال موقعیت مکانی را در نظر بگیرید.
  • هنگام درخواست به‌روزرسانی‌های موقعیت مکانی با استفاده از APIهای FusedLocationProvider یا LocationManager، سیستم به‌طور خودکار در طول فراخوانی رویداد موقعیت مکانی، دستگاه را بیدار می‌کند. این قفل بیداری کوتاه‌مدت و مدیریت‌شده توسط سیستم، از محاسبات قفل بیداری جزئی بیش از حد معاف است.
  • از ایجاد یک قفل بیداری (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 استفاده می‌کنید، استفاده از آن را به فواصل زمانی دوره‌ای و فقط زمانی که کاربر صراحتاً از طریق تعامل با رابط کاربری اجازه دسترسی داده است، کاهش دهید. نظارت بر حسگر با فرکانس بالا می‌تواند به دلیل تعداد دفعات روشن شدن و پردازش CPU، باتری را به شدت تخلیه کند.
  • اگر تعداد قدم‌ها یا مسافت طی شده را پیگیری می‌کنید، به جای استفاده از SensorManager، از Recording API استفاده کنید یا استفاده از Health Connect را برای دسترسی به تعداد قدم‌های دستگاه به صورت تاریخی و تجمیع شده در نظر بگیرید تا داده‌ها را به روشی با مصرف بهینه باتری ثبت کنید.
  • اگر در حال ثبت یک حسگر با SensorManager هستید، برای به حداقل رساندن تعداد وقفه‌های CPU و استفاده از دسته‌بندی حسگرها ، maxReportLatencyUs را 30 ثانیه یا بیشتر تعیین کنید. هنگامی که دستگاه متعاقباً توسط یک محرک دیگر مانند تعامل کاربر، بازیابی موقعیت مکانی یا یک کار برنامه‌ریزی‌شده بیدار می‌شود، سیستم بلافاصله داده‌های حسگر ذخیره‌شده را ارسال می‌کند.
  val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

sensorManager.registerListener(this,
                 accelerometer,
                 samplingPeriodUs, // How often to sample data
                 maxReportLatencyUs // Key for sensor batching 
              )
  • اگر برنامه شما به داده‌های موقعیت مکانی و حسگر نیاز دارد، بازیابی و پردازش رویداد آنها را همگام‌سازی کنید. با انتقال داده‌های حسگر به قفل بیداری کوتاه‌مدتی که سیستم برای به‌روزرسانی‌های موقعیت مکانی نگه می‌دارد، از نیاز به قفل بیداری برای بیدار نگه داشتن CPU جلوگیری می‌کنید. از یک worker یا یک قفل بیداری کوتاه‌مدت برای مدیریت آپلود و پردازش این داده‌های ترکیبی استفاده کنید.

پیام‌رسانی از راه دور

موارد استفاده مثال:

  • برنامه‌های همراه نظارت تصویری یا صوتی که نیاز به نظارت بر رویدادهایی دارند که در یک دستگاه خارجی متصل با استفاده از یک شبکه محلی رخ می‌دهند.
  • برنامه‌های پیام‌رسانی که اتصال سوکت شبکه را با نوع دسکتاپ حفظ می‌کنند.

چگونه میزان قفل شدن صفحه نمایش را کاهش دهیم:

  • اگر رویدادهای شبکه می‌توانند در سمت سرور پردازش شوند، از FCM برای دریافت اطلاعات در مورد کلاینت استفاده کنید. در صورت نیاز به پردازش بیشتر داده‌های FCM، می‌توانید یک کارگر تسریع‌شده را برنامه‌ریزی کنید.
  • اگر رویدادها باید از طریق اتصال سوکت در سمت کلاینت پردازش شوند، برای گوش دادن به وقفه‌های رویداد نیازی به قفل بیداری نیست. هنگامی که بسته‌های داده به رادیوی Wi-Fi یا تلفن همراه می‌رسند، سخت‌افزار رادیو یک وقفه سخت‌افزاری را به شکل قفل بیداری هسته فعال می‌کند. سپس می‌توانید یک کارگر را برنامه‌ریزی کنید یا یک قفل بیداری برای پردازش داده‌ها تهیه کنید.
  • برای مثال، اگر از ktor-network برای گوش دادن به بسته‌های داده در یک سوکت شبکه استفاده می‌کنید، فقط زمانی باید قفل بیداری را فعال کنید که بسته‌ها به کلاینت تحویل داده شده و نیاز به پردازش داشته باشند.
  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
         }
    }
}

خلاصه

با اتخاذ این راه‌حل‌های پیشنهادی برای موارد استفاده رایج مانند همگام‌سازی‌های پس‌زمینه، ردیابی موقعیت مکانی، نظارت بر حسگرها و ارتباطات شبکه، توسعه‌دهندگان می‌توانند در جهت کاهش استفاده غیرضروری از قفل بیدارباش تلاش کنند. برای ادامه یادگیری، پست وبلاگ فنی دیگر ما را بخوانید یا ویدیوی فنی ما در مورد نحوه کشف و اشکال‌زدایی قفل‌های بیدارباش را تماشا کنید : باتری برنامه خود را با استفاده از معیار قفل بیدارباش Android Vitals بهینه کنید . همچنین، به مستندات به‌روز شده قفل بیدارباش ما مراجعه کنید. برای کمک به ما در ادامه بهبود منابع فنی خود، لطفاً هرگونه بازخورد اضافی در مورد راهنمایی‌های ما را در نظرسنجی بازخورد مستندات ما به اشتراک بگذارید.

    نوشته شده توسط:

    ادامه مطلب