Wake lock جزئی مکانیزمی در PowerManager
API است که به توسعه دهندگان این امکان را می دهد که CPU را پس از خاموش شدن نمایشگر دستگاه (چه به دلیل وقفه زمانی سیستم یا فشار دادن دکمه پاور توسط کاربر) روشن نگه دارند. برنامه شما با فراخوانی acquire()
با پرچم PARTIAL_WAKE_LOCK
یک wake lock جزئی دریافت می کند. یک wake lock جزئی اگر زمانی که برنامه شما در پسزمینه اجرا میشود برای مدت طولانی نگه داشته شود (هیچ بخشی از برنامه شما برای کاربر قابل مشاهده نیست) گیر میکند. این وضعیت باتری دستگاه را خالی می کند زیرا از ورود دستگاه به حالت های کم مصرف جلوگیری می کند. وایک لاک های جزئی باید فقط در صورت لزوم استفاده شوند و به محض اینکه دیگر مورد نیاز نباشند آزاد شوند.
اگر برنامه شما یک قفل بیدار جزئی گیر کرده است، می توانید از راهنمایی در این صفحه برای تشخیص و رفع مشکل استفاده کنید.
مشکل را تشخیص دهید
ممکن است همیشه ندانید که wake lock های جزئی برنامه شما گیر کرده است. اگر قبلاً برنامه خود را منتشر کرده اید، Android vitals می تواند به شما کمک کند تا از مشکل آگاه شوید.
حیاتی اندروید
Android vitals میتواند با هشدار دادن به شما از طریق کنسول Play در زمانی که برنامهتان دارای wake locks گیر کرده است، به بهبود عملکرد برنامه شما کمک کند. Android vitals گزارش می دهد که wake lock جزئی در زمانی که حداقل یک ساعت طول می کشد، گیر می کند، در حالی که در پس زمینه، قفل نیمه بیدار در یک جلسه باتری رخ می دهد.
تعریف جلسه باتری به نسخه پلتفرم بستگی دارد.
- در اندروید 10، یک جلسه باتری، تجمیع تمام گزارشهای باتری دریافتی در یک دوره 24 ساعته معین است. گزارش باتری به فاصله زمانی بین دو شارژ باتری از زیر 20٪ تا بالای 80٪ یا از هر سطح شارژ تا 100٪ اشاره دارد.
- در اندروید 11، یک جلسه باتری یک دوره 24 ساعته ثابت است.
تعداد جلسات باتری نمایش داده شده در مجموع برای همه کاربران اندازه گیری شده برنامه است. برای اطلاعات در مورد نحوه جمعآوری دادههای حیاتی Android توسط Google Play، به مستندات کنسول Play مراجعه کنید.
هنگامی که متوجه شدید که برنامه شما دارای wake lockهای جزئی بیش از حد گیر کرده است، گام بعدی شما رسیدگی به این مشکل است.
مشکل را برطرف کنید
Wake lock در نسخههای اولیه پلتفرم اندروید معرفی شد، اما با گذشت زمان، بسیاری از موارد استفاده که قبلاً به wake lock نیاز داشتند، اکنون توسط APIهای جدیدتر مانند WorkManager بهتر ارائه میشوند.
این بخش حاوی نکاتی برای رفع wake lock است، اما در دراز مدت، برنامه خود را برای پیروی از توصیههای بخش بهترین شیوهها مهاجرت کنید.
مکانهایی را در کدتان که wake lock دریافت میکنند، شناسایی و اصلاح کنید، مانند تماسهایی با زیرکلاسهای newWakeLock(int, String)
یا WakefulBroadcastReceiver
. در اینجا چند نکته وجود دارد:
- توصیه می کنیم نام بسته، کلاس یا روش خود را در نام تگ wakelock قرار دهید تا بتوانید به راحتی مکانی را در منبع خود شناسایی کنید که wake lock در آن ایجاد شده است. در اینجا چند نکته اضافی وجود دارد:
- هرگونه اطلاعات شناسایی شخصی (PII) را در نام، مانند آدرس ایمیل، کنار بگذارید. در غیر این صورت، دستگاه به جای نام wake lock
_UNKNOWN
ثبت می کند. - نام کلاس یا متد را به صورت برنامهنویسی دریافت نکنید، برای مثال با فراخوانی
getName()
زیرا ممکن است توسط Proguard مبهم شود. به جای آن از یک رشته رمزگذاری شده استفاده کنید. - شمارنده یا شناسههای منحصربهفرد را به برچسبهای wake lock اضافه نکنید. سیستم قادر نخواهد بود wake lockهای ایجاد شده با همان روش را جمع آوری کند زیرا همه آنها دارای شناسه های منحصر به فرد هستند.
- هرگونه اطلاعات شناسایی شخصی (PII) را در نام، مانند آدرس ایمیل، کنار بگذارید. در غیر این صورت، دستگاه به جای نام wake lock
مطمئن شوید که کد شما تمام wake lock هایی را که به دست می آورد آزاد می کند. این بسیار پیچیده تر از اطمینان از این است که هر فراخوانی
acquire()
دارای یک فراخوانی مربوط بهrelease()
باشد. در اینجا یک نمونه از wake lock است که به دلیل یک استثنای نامشخص آزاد نمی شود:کاتلین
@Throws(MyException::class) fun doSomethingAndRelease() { wakeLock.apply { acquire() doSomethingThatThrows() release() // does not run if an exception is thrown } }
جاوا
void doSomethingAndRelease() throws MyException { wakeLock.acquire(); doSomethingThatThrows(); wakeLock.release(); // does not run if an exception is thrown }
این یک نسخه صحیح از کد است:
کاتلین
@Throws(MyException::class) fun doSomethingAndRelease() { wakeLock.apply { try { acquire() doSomethingThatThrows() } finally { release() } } }
جاوا
void doSomethingAndRelease() throws MyException { try { wakeLock.acquire(); doSomethingThatThrows(); } finally { wakeLock.release(); } }
مطمئن شوید که wake lock ها به محض اینکه دیگر مورد نیاز نیستند آزاد شوند. به عنوان مثال، اگر از wake lock برای اجازه دادن به یک کار پسزمینه استفاده میکنید، مطمئن شوید که انتشار آن پس از اتمام آن کار انجام میشود. اگر wake lock بیش از حد انتظار نگه داشته شود بدون اینکه آزاد شود، این می تواند به این معنی باشد که کار پس زمینه شما بیشتر از حد انتظار زمان می برد.
پس از رفع مشکل در کد، با استفاده از ابزار Android زیر بررسی کنید که برنامه شما به درستی wake lock را آزاد می کند:
dumpsys - ابزاری است که اطلاعاتی در مورد وضعیت خدمات سیستم در یک دستگاه ارائه می دهد. برای مشاهده وضعیت سرویس پاور، که شامل لیستی از wake lockها است،
adb shell dumpsys power
اجرا کنید.Battery Historian - ابزاری که خروجی گزارش اشکال اندروید را به نمایشی بصری از رویدادهای مرتبط با انرژی تجزیه می کند.
بهترین شیوه ها
به طور کلی، برنامه شما باید از wake lock جزئی اجتناب کند زیرا تخلیه باتری کاربر بسیار آسان است. Android APIهای جایگزینی را برای تقریباً هر موردی که قبلاً نیاز به قفل بخشی جزئی داشت ارائه می دهد. یکی از موارد استفاده باقی مانده برای wake lock های جزئی اطمینان از ادامه پخش برنامه موسیقی در زمانی که صفحه نمایش خاموش است. اگر از wake lock برای اجرای وظایف استفاده می کنید، گزینه های توضیح داده شده در راهنمای پردازش پس زمینه را در نظر بگیرید.
اگر باید از wake lock های جزئی استفاده کنید، توصیه های زیر را دنبال کنید:
- مطمئن شوید که بخشی از برنامه شما در پیش زمینه باقی می ماند. به عنوان مثال، اگر نیاز به اجرای یک سرویس دارید، به جای آن یک سرویس پیش زمینه راه اندازی کنید . این به صورت بصری به کاربر نشان می دهد که برنامه شما هنوز در حال اجرا است.
- مطمئن شوید که منطق به دست آوردن و آزاد کردن wake lock تا حد امکان ساده است. هنگامی که منطق wake lock شما به ماشینهای حالت پیچیده، زمانبندیها، استخرهای اجرایی و/یا رویدادهای برگشتی متصل است، هر گونه اشکال ظریف در آن منطق میتواند باعث شود که wake lock بیشتر از حد انتظار باقی بماند. تشخیص و رفع اشکال این باگ ها دشوار است.
برای شما توصیه می شود
- توجه: وقتی جاوا اسکریپت خاموش است، متن پیوند نمایش داده می شود
- قاب های یخ زده
- معیارها را در Continuous Integration اجرا کنید
- ایجاد و اندازه گیری پروفایل های پایه بدون Macrobenchmark