در اندروید 9 و بالاتر، این پلتفرم میتواند برنامهها را از نظر رفتاری که بر عمر باتری دستگاهها تأثیر منفی میگذارد نظارت کند. این پلتفرم از قوانین راه اندازی استفاده و ارزیابی می کند تا یک جریان UX ارائه دهد که به کاربران این امکان را می دهد تا برنامه هایی را که قوانین را نقض می کنند محدود کنند.
در اندروید 8.0 و پایینتر، محدودیتهایی از طریق ویژگیهایی مانند Doze، آماده به کار برنامه، محدودیتهای پسزمینه و محدودیتهای موقعیت مکانی پسزمینه وجود داشت. با این حال، برخی از برنامهها همچنان رفتارهای بدی از خود نشان میدهند، که برخی از آنها در Android vitals توضیح داده شدهاند. اندروید 9 زیرساخت سیستم عاملی را معرفی کرد که میتواند برنامهها را بر اساس قوانین راهاندازی شناسایی و محدود کند که میتوانند در طول زمان بهروزرسانی شوند.
محدودیت های پس زمینه
کاربران میتوانند برنامهها را محدود کنند یا سیستم ممکن است برنامههایی را پیشنهاد دهد که تشخیص میدهد بر سلامت دستگاه تأثیر منفی میگذارند.
برنامه های محدود شده:
- هنوز هم کاربر می تواند راه اندازی شود.
- نمیتوان مشاغل/زنگها را اجرا کرد یا از شبکه در پسزمینه استفاده کرد.
- نمی توان سرویس های پیش زمینه را اجرا کرد.
- می تواند توسط کاربر به یک برنامه نامحدود تغییر یابد.
پیادهکنندههای دستگاه میتوانند محدودیتهای اضافی را به برنامهها اضافه کنند تا:
- برنامه را از راه اندازی مجدد خود محدود کنید.
- محدود کردن خدمات از محدود بودن (بسیار خطرناک).
برنامههای محدود شده در پسزمینه انتظار نمیرود منابع دستگاهی مانند حافظه، CPU و باتری را مصرف کنند. وقتی کاربر به طور فعال از آن برنامهها استفاده نمیکند، برنامههای دارای محدودیت پسزمینه نباید بر سلامت دستگاه تأثیر بگذارند. با این حال، انتظار می رود زمانی که کاربر برنامه ها را راه اندازی می کند، همان برنامه ها کاملاً کاربردی باشند.
از پیاده سازی های سفارشی استفاده کنید
پیادهکنندههای دستگاه میتوانند به استفاده از روشهای سفارشی خود برای اعمال محدودیتها بر روی برنامهها ادامه دهند.
ادغام محدودیت های برنامه
بخشهای زیر نحوه تعریف و ادغام محدودیتهای برنامه را در دستگاه خود شرح میدهند. اگر از روشهای محدود کردن برنامه اندروید 8.x یا پایینتر استفاده میکنید، بخشهای زیر را از نزدیک برای تغییرات در Android 9 و بالاتر مرور کنید.
پرچم AppOpsManager را تنظیم کنید
وقتی یک برنامه محدود است، پرچم مناسب را در AppOpsManager
تنظیم کنید. یک نمونه کد کد از packages/apps/Settings/src/com/android/settings/fuelgauge/BatteryUtils.java
:
public void setForceAppStandby(int uid, String packageName, int mode) { final boolean isPreOApp = isPreOApp(packageName); if (isPreOApp) { // Control whether app could run in the background if it is pre O app mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName, mode); } // Control whether app could run jobs in the background mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName, mode); }
مطمئن شوید که isBackgroundRestricted درست است
وقتی یک برنامه محدود می شود، مطمئن شوید که ActivityManager.isBackgroundRestricted()
true
برمی گرداند.
دلیل محدودیت را ثبت کنید
وقتی برنامه ای محدود شده است، دلایل محدودیت را ثبت کنید. یک نمونه کد کد ورود به سیستم از packages/apps/Settings/src/com/android/settings/fuelgauge/batterytip/actions/RestrictAppAction.java
:
mBatteryUtils.setForceAppStandby(mBatteryUtils.getPackageUid(packageName), packageName,AppOpsManager.MODE_IGNORED); if (CollectionUtils.isEmpty(appInfo.anomalyTypes)) { // Only log context if there is no anomaly type mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_TIP_RESTRICT_APP, packageName, Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT,metricsKey)); } else { // Log ALL the anomaly types for (int type : appInfo.anomalyTypes) { mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_TIP_RESTRICT_APP, packageName, Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, metricsKey), Pair.create(MetricsProto.MetricsEvent.FIELD_ANOMALY_TYPE, type)); }
مقدار AnomalyType
را جایگزین type
کنید.
پیادهکنندههای دستگاه میتوانند از ثابتهای تعریفشده در src/com/android/settings/fuelgauge/batterytip/StatsManagerConfig.java
استفاده کنند:
public @interface AnomalyType { // This represents an error condition in the anomaly detection. int NULL = -1; // The anomaly type does not match any other defined type. int UNKNOWN_REASON = 0; // The application held a partial (screen off) wake lock for a period of time that // exceeded the threshold with the screen off when not charging. int EXCESSIVE_WAKELOCK_ALL_SCREEN_OFF = 1; // The application exceeded the maximum number of wakeups while in the background // when not charging. int EXCESSIVE_WAKEUPS_IN_BACKGROUND = 2; // The application did unoptimized Bluetooth scans too frequently when not charging. int EXCESSIVE_UNOPTIMIZED_BLE_SCAN = 3; // The application ran in the background for a period of time that exceeded the // threshold. int EXCESSIVE_BACKGROUND_SERVICE = 4; // The application exceeded the maximum number of wifi scans when not charging. int EXCESSIVE_WIFI_SCAN = 5; // The application exceed the maximum number of flash writes int EXCESSIVE_FLASH_WRITES = 6; // The application used more than the maximum memory, while not spending any time // in the foreground. int EXCESSIVE_MEMORY_IN_BACKGROUND = 7; // The application exceeded the maximum percentage of frames with a render rate of // greater than 700ms. int EXCESSIVE_DAVEY_RATE = 8; // The application exceeded the maximum percentage of frames with a render rate // greater than 16ms. int EXCESSIVE_JANKY_FRAMES = 9; // The application exceeded the maximum cold start time - the app has not been // launched since last system start, died or was killed. int SLOW_COLD_START_TIME = 10; // The application exceeded the maximum hot start time - the app and activity are // already in memory. int SLOW_HOT_START_TIME = 11; // The application exceeded the maximum warm start time - the app was already in // memory but the activity wasn't created yet or was removed from memory. int SLOW_WARM_START_TIME = 12; // The application exceeded the maximum number of syncs while in the background. int EXCESSIVE_BACKGROUND_SYNCS = 13; // The application exceeded the maximum number of gps scans while in the background. int EXCESSIVE_GPS_SCANS_IN_BACKGROUND = 14; // The application scheduled more than the maximum number of jobs while not charging. int EXCESSIVE_JOB_SCHEDULING = 15; // The application exceeded the maximum amount of mobile network traffic while in // the background. int EXCESSIVE_MOBILE_NETWORK_IN_BACKGROUND = 16; // The application held the WiFi lock for more than the maximum amount of time while // not charging. int EXCESSIVE_WIFI_LOCK_TIME = 17; // The application scheduled a job that ran longer than the maximum amount of time. int JOB_TIMED_OUT = 18; // The application did an unoptimized Bluetooth scan that exceeded the maximum // time while in the background. int LONG_UNOPTIMIZED_BLE_SCAN = 19; // The application exceeded the maximum ANR rate while in the background. int BACKGROUND_ANR = 20; // The application exceeded the maximum crash rate while in the background. int BACKGROUND_CRASH_RATE = 21; // The application exceeded the maximum ANR-looping rate. int EXCESSIVE_ANR_LOOPING = 22; // The application exceeded the maximum ANR rate. int EXCESSIVE_ANRS = 23; // The application exceeded the maximum crash rate. int EXCESSIVE_CRASH_RATE = 24; // The application exceeded the maximum crash-looping rate. int EXCESSIVE_CRASH_LOOPING = 25; // The application crashed because no more file descriptors were available. int NUMBER_OF_OPEN_FILES = 26; }
هنگامی که کاربر یا سیستم محدودیت های یک برنامه را حذف می کند، باید دلایل حذف محدودیت ها را ثبت کنید. یک نمونه کد کد ورود به سیستم از packages/apps/Settings/src/com/android/settings/fuelgauge/batterytip/actions/UnrestrictAppAction.java
:
public void handlePositiveAction(int metricsKey) { final AppInfo appInfo = mUnRestrictAppTip.getUnrestrictAppInfo(); // Clear force app standby, then app can run in the background mBatteryUtils.setForceAppStandby(appInfo.uid, appInfo.packageName, AppOpsManager.MODE_ALLOWED); mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_TIP_UNRESTRICT_APP, appInfo.packageName, Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, metricsKey)); }
تست محدودیت های اپلیکیشن
برای تست رفتار محدودیت های برنامه در اندروید 9 و بالاتر، از یکی از دستورات زیر استفاده کنید:
- یک برنامه را در محدودیت قرار دهید:
appops set package-name RUN_ANY_IN_BACKGROUND ignore
- یک برنامه را از محدودیت خارج کنید و رفتار پیش فرض را بازیابی کنید:
appops set package-name RUN_ANY_IN_BACKGROUND allow
- برنامهای را در پسزمینه فوراً غیرفعال کنید:
am make-uid-idle [--user user-id | all | current] package-name
- یک بسته را برای مدت کوتاهی به
tempwhitelist
اضافه کنید:cmd deviceidle tempwhitelist [-u user] [-d duration] [package package-name]
- افزودن/حذف بسته از لیست سفید کاربر:
cmd deviceidle whitelist [+/-]package-name
- وضعیت داخلی
jobscheduler
و مدیر زنگ هشدار را بررسی کنید:dumpsys jobscheduler
dumpsys alarm
آماده به کار برنامه
آماده به کار برنامه با به تعویق انداختن فعالیت شبکه پسزمینه و کارهای برنامههایی که کاربر فعالانه از آنها استفاده نمیکند، عمر باتری را افزایش میدهد.
چرخه عمر برنامه آماده به کار
این پلتفرم برنامههای غیرفعال را شناسایی میکند و آنها را در حالت آماده به کار قرار میدهد تا زمانی که کاربر فعالانه با برنامه درگیر شود.
در مرحله تشخیص ، پلتفرم تشخیص میدهد که وقتی دستگاه شارژ نمیشود و کاربر بهطور مستقیم یا غیرمستقیم برنامه را برای مدت زمان مشخصی از ساعت و همچنین مقدار مشخصی از زمان روشن شدن صفحه نمایش، برنامه را راهاندازی نکرده است، برنامه تشخیص میدهد که غیرفعال است. . (راه اندازی غیرمستقیم زمانی رخ می دهد که یک برنامه پیش زمینه به یک سرویس در برنامه دوم دسترسی پیدا کند.)
در طول آماده به کار برنامه ، پلت فرم از دسترسی برنامهها به شبکه بیش از یک بار در روز جلوگیری میکند و همگامسازی برنامهها و کارهای دیگر را به تعویق میاندازد.
زمانی که پلتفرم برنامه را از حالت آماده به کار خارج می کند :
- برنامه فعال می شود.
- دستگاه به برق وصل شده و شارژ می شود.
برنامه های فعال تحت تأثیر برنامه آماده به کار قرار نمی گیرند. یک برنامه زمانی فعال است که:
- فرآیندی که در حال حاضر در پیش زمینه است (به عنوان یک فعالیت یا خدمات پیش زمینه، یا در حال استفاده توسط فعالیت یا سرویس پیش زمینه دیگر)، مانند شنونده اعلان، خدمات دسترسی، تصویر زمینه زنده و غیره.
- اعلانی که کاربر مشاهده می کند، مانند صفحه قفل یا سینی اعلان
- به صراحت توسط کاربر راه اندازی شده است
اگر هیچ یک از فعالیت های فوق برای مدتی انجام نشده باشد، برنامه غیرفعال است.
تست آماده به کار برنامه
با استفاده از دستورات adb
زیر می توانید به صورت دستی برنامه آماده به کار را آزمایش کنید:
adb shell dumpsys battery unplug
adb shell am set-idle package-name true
adb shell am set-idle package-name false
adb shell am get-idle package-name