بهینه‌سازی مصرف داده شبکه

در طول عمر تلفن هوشمند، هزینه طرح داده تلفن همراه به‌راحتی می‌تواند از هزینه خود دستگاه بیشتر شود. در Android نسخه ۷.۰ (سطح میانای برنامه‌سازی کاربردی ۲۴) و بالاتر، کاربران می‌توانند «صرفه‌جویی داده» را در سراسر دستگاه فعال کنند تا مصرف داده دستگاهشان را بهینه‌سازی کنند و از داده کمتری استفاده کنند. این قابلیت به‌ویژه هنگام رومینگ، نزدیک به پایان چرخه صورت‌حساب، یا برای بسته داده پیش‌پرداخت کوچک مفید است.

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

‫Android 7.0 (سطح API‏ ۲۴) ConnectivityManager API را گسترش می‌دهد تا راهی برای بازیابی اولویت‌های «صرفه‌جویی داده» کاربر و پایش تغییرات اولویت دراختیار برنامه‌ها قرار دهد. بهتر است برنامه‌ها بررسی کنند که آیا کاربر «صرفه‌جویی داده» را فعال کرده است یا نه و تلاش کنند مصرف داده پیش‌زمینه و پس‌زمینه را محدود کنند.

بررسی اولویت‌های صرفه‌جویی داده

در Android نسخه ۷.۰ (سطح میانای برنامه‌سازی کاربردی ۲۴) و بالاتر، برنامه‌ها می‌توانند از ConnectivityManager API برای تعیین محدودیت‌های اعمال‌شده بر مصرف داده استفاده کنند. روش getRestrictBackgroundStatus() یکی از مقادیر زیر را برمی‌گرداند:

RESTRICT_BACKGROUND_STATUS_DISABLED
«صرفه‌جویی داده» غیرفعال است.
RESTRICT_BACKGROUND_STATUS_ENABLED
کاربر «صرفه‌جویی داده» را برای این برنامه فعال کرده است. برنامه‌ها باید تلاش کنند مصرف داده را در پیش‌زمینه محدود کنند و محدودیت‌های مصرف داده پس‌زمینه را به‌درستی مدیریت کنند.
RESTRICT_BACKGROUND_STATUS_WHITELISTED
کاربر «صرفه‌جویی داده» را فعال کرده است اما برنامه اجازه دارد آن را دور بزند. برنامه‌ها همچنان باید تلاش کنند مصرف داده پیش‌زمینه و پس‌زمینه را محدود کنند.

هرگاه دستگاه به شبکه با هزینه براساس مصرف متصل است، استفاده از داده را محدود کنید، حتی اگر «صرفه‌جویی داده» غیرفعال باشد یا برنامه اجازه داشته باشد آن را دور بزند. کد نمونه زیر از ConnectivityManager.isActiveNetworkMetered() و ConnectivityManager.getRestrictBackgroundStatus() برای تعیین مقدار داده‌ای که برنامه باید استفاده کند استفاده می‌کند:

کاتلین

(getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).apply {
    // Checks if the device is on a metered network
    if (isActiveNetworkMetered) {
        // Checks user’s Data Saver settings.
        when (restrictBackgroundStatus) {
            RESTRICT_BACKGROUND_STATUS_ENABLED -> {
                // Background data usage is blocked for this app. Wherever possible,
                // the app should also use less data in the foreground.
            }
            RESTRICT_BACKGROUND_STATUS_WHITELISTED -> {
                // The app is allowed to bypass Data Saver. Nevertheless, wherever possible,
                // the app should use less data in the foreground and background.
            }
            RESTRICT_BACKGROUND_STATUS_DISABLED -> {
                // Data Saver is disabled. Since the device is connected to a
                // metered network, the app should use less data wherever possible.
            }
        }
    } else {
        // The device is not on a metered network.
        // Use data as required to perform syncs, downloads, and updates.
    }
}

جاوا

ConnectivityManager connMgr = (ConnectivityManager)
        getSystemService(Context.CONNECTIVITY_SERVICE);
// Checks if the device is on a metered network
if (connMgr.isActiveNetworkMetered()) {
  // Checks user’s Data Saver settings.
  switch (connMgr.getRestrictBackgroundStatus()) {
    case RESTRICT_BACKGROUND_STATUS_ENABLED:
    // Background data usage is blocked for this app. Wherever possible,
    // the app should also use less data in the foreground.

    case RESTRICT_BACKGROUND_STATUS_WHITELISTED:
    // The app is allowed to bypass Data Saver. Nevertheless, wherever possible,
    // the app should use less data in the foreground and background.

    case RESTRICT_BACKGROUND_STATUS_DISABLED:
    // Data Saver is disabled. Since the device is connected to a
    // metered network, the app should use less data wherever possible.
  }
} else {
  // The device is not on a metered network.
  // Use data as required to perform syncs, downloads, and updates.
}

توجه: این رفتار در Android TV متفاوت است. Android TV به‌جای مسدود کردن استفاده در پس‌زمینه، فقط آن را محدود می‌کند. وقتی برنامه‌ها در پیش‌زمینه باشند، به ۸۰۰ کیلوبیت در ثانیه محدود می‌شوند و وقتی در پس‌زمینه باشند، به ۱۰ کیلوبیت در ثانیه محدود می‌شوند. از ConnectivityManager.isActiveNetworkMetered() برای تشخیص زمان محدود کردن مصرف داده در تلویزیون استفاده کنید.

درخواست اجازه‌های محدودیت داده

اگر برنامه‌تان نیاز به استفاده از داده در پس‌زمینه دارد، می‌تواند با ارسال هدف Settings.ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS حاوی URI نام بسته برنامه‌تان، برای مثال package:MY_APP_ID، اجازه‌های محدودیت داده را درخواست کند.

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

نظارت بر تغییرات اولویت‌های «صرفه‌جویی داده»

برنامه‌ها می‌توانند با ایجاد BroadcastReceiver برای گوش دادن به ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED و ثبت پویای گیرنده با Context.registerReceiver()، تغییرات اولویت‌های «صرفه‌جویی داده» را پایش کنند. وقتی برنامه‌ای این پخش را دریافت می‌کند، باید با فراخوانی ConnectivityManager.getRestrictBackgroundStatus() بررسی کند که آیا اولویت‌های جدید «صرفه‌جویی داده» بر اجازه‌های آن تأثیر می‌گذارد یا نه.

توجه: سیستم این پخش را فقط به برنامه‌هایی ارسال می‌کند که به‌طور پویا برای آن‌ها با Context.registerReceiver() ثبت‌نام می‌کنند. برنامه‌هایی که برای دریافت این همه‌فرستی در مانیفست خود ثبت‌نام می‌کنند، آن‌ها را دریافت نخواهند کرد.

آزمایش با فرمان‌های «پل اشکال‌زدایی Android»

Android Debug Bridge (ADB) چند فرمان ارائه می‌دهد که می‌توانید از آن‌ها برای آزمایش برنامه‌تان در شرایط «صرفه‌جویی داده» استفاده کنید. می‌توانید اجازه‌های شبکه را بررسی و پیکربندی کنید یا شبکه‌های بی‌سیم را به‌عنوان شبکه‌های با هزینه براساس میزان مصرف تنظیم کنید تا برنامه‌تان را در شبکه‌های بدون هزینه براساس میزان مصرف آزمایش کنید.

$ adb shell dumpsys netpolicy
گزارشی تولید می‌کند که شامل تنظیمات محدودیت شبکه پس‌زمینه جهانی فعلی، UID بسته‌هایی که درحال‌حاضر مجاز به دور زدن «صرفه‌جویی داده» هستند، و اجازه‌های شبکه سایر بسته‌های شناخته‌شده است.
$ adb shell cmd netpolicy
فهرست کاملی از فرمان‌های «مدیر خط‌مشی شبکه» (netpolicy) را نمایش می‌دهد.
$ adb shell cmd netpolicy set restrict-background <boolean>
به‌ترتیب با ارسال true یا false، حالت «صرفه‌جویی داده» را فعال یا غیرفعال می‌کند.
$ adb shell cmd netpolicy add restrict-background-whitelist <UID>
شناسه کاربری بسته مشخص‌شده را به فهرست مجاز (whitelist) اضافه می‌کند تا استفاده از داده محدودشده در پس‌زمینه مجاز شود.
$ adb shell cmd netpolicy remove restrict-background-whitelist <UID>
شناسه کاربری بسته مشخص‌شده را از فهرست مجاز (whitelist) برمی‌دارد تا استفاده از داده‌های شبکه‌ای پس‌زمینه را درحین فعال بودن «صرفه‌جویی داده» مسدود کند.
$ adb shell cmd netpolicy list wifi-networks
همه شبکه‌های wifi را فهرست می‌کند و نشان می‌دهد که آیا شبکه‌ها محدود هستند یا نه.
$ adb shell cmd netpolicy set metered-network <WIFI_SSID> true
Wi-Fi را با SSID مشخص‌شده به‌عنوان با حجم محدود تنظیم می‌کند و به شما امکان می‌دهد شبکه با حجم محدود را در شبکه بدون حجم محدود شبیه‌سازی کنید.