Düzenli güncellemelerin etkisini en aza indirme

Uygulamanızın ağa gönderdiği istekler pil tüketiminin önemli bir nedenidir çünkü güç tüketen hücresel veya kablosuz radyoları açtılar. Gücün ötesi Bu radyolar, paket gönderip almak için gerekenden daha az güç ve uyanık tutmaya çalışın. Her 15 saniyede bir ağ isteği gibi basit bir işlem mobil radyo sürekli olarak açık kalabilir ve pil hızlı bir şekilde tükenebilir güç.

Düzenli olarak yapılan üç genel güncelleme türü vardır:

  • Kullanıcı tarafından başlatılır. Aşağıdaki gibi bazı kullanıcı davranışlarına dayalı bir güncelleme yapılması yenilemek için çekme hareketidir.
  • Uygulama tarafından başlatılan. Düzenli olarak güncelleme yapma.
  • Sunucu tarafından başlatıldı. Şu kaynaktan gelen bildirime yanıt olarak güncelleme yapılması: daha iyi olur.

Bu konu, bunların her birini ele alır ve bunları ele almanın yollarını optimize edilmiş bir uygulamadır.

Kullanıcı tarafından başlatılan istekleri optimize edin

Kullanıcı tarafından başlatılan istekler genellikle bazı kullanıcı davranışlarına yanıt olarak ortaya çıkar. Örneğin, Örneğin, en son haber makalelerini okumak için kullanılan bir uygulama, kullanıcının yeni makaleleri kontrol etmek için yenilemek üzere çekme hareketi yapın. URL parametrelerinin Google tarafından nasıl ele alınmasını istediğinizi belirtmek için optimizasyon sırasında kullanıcı tarafından başlatılan isteklere yanıt vermek için ağ kullanımı.

Kullanıcı isteklerini kısıtlayın

Kullanıcı tarafından başlatılan bazı isteklere Örneğin kısa bir süre boyunca birden fazla yenilemek için çekme mevcut veriler hâlâ güncelken yeni veriler olup olmadığını kontrol etmek. Her biri için işlem yapma isteği, radyoyu açık tutarak önemli miktarda güç israfına neden olabilir. CEVAP en verimli olanı, kullanıcı tarafından başlatılan istekleri belirli bir süre içinde yalnızca bir istekte bulunulabilir; bu da biraz zaman alır.

Önbellek kullanma

Uygulamanızın verilerini önbelleğe alarak bilgilerin yerel bir kopyasını oluşturursunuz en iyi uygulamaları paylaşacağız. Böylece uygulamanız, bilgileri bir ağ açmak zorunda kalmadan birden çok kez kopyalayın bağlantıyı tıklayın.

Statik alanlar da dahil olmak üzere verileri mümkün olduğunca agresif bir şekilde önbelleğe almalısınız. kaynakları ve tam boyutlu resimler gibi isteğe bağlı indirmeleri HTTP kullanabilirsiniz engellemek için önbellek üstbilgilerini kullanır ve böylece önbelleğe alma stratejinizin eski veriler görüntüleniyor. Ağ yanıtlarını önbelleğe alma hakkında daha fazla bilgi için bkz. Gereksiz sayıdan kaçının indirme başlıklı makaleye bakın.

Uygulamanız, Android 11 ve sonraki sürümlerde kullanım alanları için kullanılan uygulamalardan bahsedeceğiz. uygulamanın paylaşılan bir veri kümesine erişmesi gerekiyorsa önce uygulamanın önbelleğe alınmış bir sürümünü kontrol edebilir kontrol edin. Paylaşılan veri kümeleri hakkında daha fazla bilgi edinmek için Paylaşılan veri kümelerine erişim adlı makaleyi inceleyin.

Daha az sıklıkta daha fazla veri indirmek için daha yüksek bant genişliği kullanın

Kablosuz bir radyo üzerinden bağlandığında, daha yüksek bant genişliği genellikle daha yüksek pil maliyetidir. Diğer bir deyişle, 5G genelde daha fazla enerji tüketir. LTE'den daha pahalıya mal oluyor.

Bu, altta yatan radyo durumu, YouTube'da ve genel olarak eyaletin göreceli pil etkisiyle daha yüksek bant genişliğine sahip radyolar için kuyruk süresinin değiştirilmesi daha fazladır. Daha fazla bilgi için kuyruk süresi, bkz. Radyo durumu hakkında daha fazla bilgi edinin.

Aynı zamanda, bant genişliğinin yüksek olması daha fazla veriyi önceden aynı anda daha fazla veri indirir. Belki daha az daha yüksektir, çünkü kuyruk süresinde pil maliyeti nispeten daha yüksektir Böylece her aktarım sırasında radyonun daha uzun süre etkin kalması oturumlarını bir arada kullanma yollarını inceleyeceğiz.

Örneğin, bir LTE radyonun bant genişliği iki katına çıkarken enerji maliyeti iki katına çıkarsa kullanıyorsanız her oturumda dört kat daha fazla veri indirmeniz gerekir. 10 MB'a kadar ekleyebilirsiniz. Bu kadar fazla veriyi indirirken Önceden getirme işleminin kullanılabilir yerel depolama ve temizleme üzerindeki etkisini göz önünde bulundurun düzenli olarak kontrol edebilirsiniz.

URL parametrelerinin Google tarafından nasıl ele alınmasını istediğinizi belirtmek için Kaydolmak için ConnectivityManager varsayılan ağ için bir işleyici ve Kaydolmak için TelephonyManager PhoneStateListener geçerli cihaz bağlantı türünü belirler. Bağlantı türü öğrenildiğinde önceden getirme rutinlerinizi buna göre değiştirebilirsiniz:

Kotlin

val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val tm = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager

private var hasWifi = false
private var hasCellular = false
private var cellModifier: Float = 1f

private val networkCallback = object : ConnectivityManager.NetworkCallback() {
    // Network capabilities have changed for the network
    override fun onCapabilitiesChanged(
            network: Network,
            networkCapabilities: NetworkCapabilities
    ) {
        super.onCapabilitiesChanged(network, networkCapabilities)
        hasCellular = networkCapabilities
    .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
        hasWifi = networkCapabilities
    .hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
    }
}

private val phoneStateListener = object : PhoneStateListener() {
override fun onPreciseDataConnectionStateChanged(
    dataConnectionState: PreciseDataConnectionState
) {
  cellModifier = when (dataConnectionState.networkType) {
      TelephonyManager.NETWORK_TYPE_LTE or TelephonyManager.NETWORK_TYPE_HSPAP -> 4f
      TelephonyManager.NETWORK_TYPE_EDGE or TelephonyManager.NETWORK_TYPE_GPRS -> 1/2f
      else -> 1f

  }
}

private class NetworkState {
    private var defaultNetwork: Network? = null
    private var defaultCapabilities: NetworkCapabilities? = null
    fun setDefaultNetwork(network: Network?, caps: NetworkCapabilities?) = synchronized(this) {
        defaultNetwork = network
        defaultCapabilities = caps
    }
    val isDefaultNetworkWifi
        get() = synchronized(this) {
            defaultCapabilities?.hasTransport(TRANSPORT_WIFI) ?: false
        }
    val isDefaultNetworkCellular
        get() = synchronized(this) {
            defaultCapabilities?.hasTransport(TRANSPORT_CELLULAR) ?: false
        }
    val isDefaultNetworkUnmetered
        get() = synchronized(this) {
            defaultCapabilities?.hasCapability(NET_CAPABILITY_NOT_METERED) ?: false
        }
    var cellNetworkType: Int = TelephonyManager.NETWORK_TYPE_UNKNOWN
        get() = synchronized(this) { field }
        set(t) = synchronized(this) { field = t }
    private val cellModifier: Float
        get() = synchronized(this) {
            when (cellNetworkType) {
                TelephonyManager.NETWORK_TYPE_LTE or TelephonyManager.NETWORK_TYPE_HSPAP -> 4f
                TelephonyManager.NETWORK_TYPE_EDGE or TelephonyManager.NETWORK_TYPE_GPRS -> 1 / 2f
                else -> 1f
            }
        }
    val prefetchCacheSize: Int
        get() = when {
            isDefaultNetworkWifi -> MAX_PREFETCH_CACHE
            isDefaultNetworkCellular -> (DEFAULT_PREFETCH_CACHE * cellModifier).toInt()
            else -> DEFAULT_PREFETCH_CACHE
        }
}
private val networkState = NetworkState()
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
    // Network capabilities have changed for the network
    override fun onCapabilitiesChanged(
            network: Network,
            networkCapabilities: NetworkCapabilities
    ) {
        networkState.setDefaultNetwork(network, networkCapabilities)
    }

    override fun onLost(network: Network?) {
        networkState.setDefaultNetwork(null, null)
    }
}

private val telephonyCallback = object : TelephonyCallback(), TelephonyCallback.PreciseDataConnectionStateListener {
    override fun onPreciseDataConnectionStateChanged(dataConnectionState: PreciseDataConnectionState) {
        networkState.cellNetworkType = dataConnectionState.networkType
    }
}

connectivityManager.registerDefaultNetworkCallback(networkCallback)
telephonyManager.registerTelephonyCallback(telephonyCallback)


private val prefetchCacheSize: Int
get() {
    return when {
        hasWifi -> MAX_PREFETCH_CACHE
        hasCellular -> (DEFAULT_PREFETCH_CACHE * cellModifier).toInt()
        else -> DEFAULT_PREFETCH_CACHE
    }
}

}

Java

ConnectivityManager cm =
 (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
TelephonyManager tm =
  (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

private boolean hasWifi = false;
private boolean hasCellular = false;
private float cellModifier = 1f;

private ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onCapabilitiesChanged(
    @NonNull Network network,
    @NonNull NetworkCapabilities networkCapabilities
) {
        super.onCapabilitiesChanged(network, networkCapabilities);
        hasCellular = networkCapabilities
    .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
        hasWifi = networkCapabilities
    .hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
}
};

private PhoneStateListener phoneStateListener = new PhoneStateListener() {
@Override
public void onPreciseDataConnectionStateChanged(
    @NonNull PreciseDataConnectionState dataConnectionState
    ) {
    switch (dataConnectionState.getNetworkType()) {
        case (TelephonyManager.NETWORK_TYPE_LTE |
            TelephonyManager.NETWORK_TYPE_HSPAP):
            cellModifier = 4;
            Break;
        case (TelephonyManager.NETWORK_TYPE_EDGE |
            TelephonyManager.NETWORK_TYPE_GPRS):
            cellModifier = 1/2.0f;
            Break;
        default:
            cellModifier = 1;
            Break;
    }
}
};

cm.registerDefaultNetworkCallback(networkCallback);
tm.listen(
phoneStateListener,
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE
);

public int getPrefetchCacheSize() {
if (hasWifi) {
    return MAX_PREFETCH_SIZE;
}
if (hasCellular) {
    return (int) (DEFAULT_PREFETCH_SIZE * cellModifier);
    }
return DEFAULT_PREFETCH_SIZE;
}

Uygulama tarafından başlatılan istekleri optimize edin

Uygulama tarafından başlatılan istekler genellikle bir plana göre gerçekleşir. Örneğin, günlükleri veya analizleri arka uç hizmetine ekleyebilirsiniz. Uygulama tarafından başlatılan bu isteklerin önceliğini göz önünde bulundurun. Bu isteklerin toplu halde mi ve cihaz şarj olana kadar veya cihaz şarj olana kadar sınırsız bir ağa bağlıdır. Bu istekler, dikkatle optimize edilebilir. zaman çizelgesi oluşturma ve WorkManager değerleridir.

Toplu ağ istekleri

Mobil cihazlarda radyoyu açma, bağlantı kurma, çok fazla güç tüketir. İşte bu nedenle istekleri rastgele işlemek, önemli miktarda güç tüketebilir yardımcı olabilir. Daha verimli bir yaklaşım ise bir grup ağı ve bunları birlikte işleme koymalısınız. Bu, sistemin gereken gücü ödemesine olanak tanır. için yalnızca bir kez açmanın maliyetini karşılar. bir uygulamadır.

WorkManager'ı kullanma

Verimli bir program dahilinde iş yapmak için WorkManager kitaplığını kullanabilirsiniz ağ kullanılabilirliği gibi belirli koşulların karşılanıp karşılanmadığını dikkate alan ve güç durumu. Örneğin, Worker alt sınıf adlandırıldı En son haber başlıklarını alan DownloadHeadlinesWorker. Bu çalışan Cihazın bir Özel bir yeniden deneme stratejisi sayesinde, sınırsız ağın ve cihazın pil seviyesinin düşük olması verileri alırken herhangi bir sorun olursa aşağıdaki adımları uygulayın:

Kotlin

val constraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.UNMETERED)
    .setRequiresBatteryNotLow(true)
    .build()
val request =
    PeriodicWorkRequestBuilder<DownloadHeadlinesWorker>(1, TimeUnit.HOURS)
        .setConstraints(constraints)
        .setBackoffCriteria(BackoffPolicy.LINEAR, 1L, TimeUnit.MINUTES)
        .build()
WorkManager.getInstance(context).enqueue(request)

Java

Constraints constraints = new Constraints.Builder()
        .setRequiredNetworkType(NetworkType.UNMETERED)
        .setRequiresBatteryNotLow(true)
        .build();
WorkRequest request = new PeriodicWorkRequest.Builder(DownloadHeadlinesWorker.class, 1, TimeUnit.HOURS)
        .setBackoffCriteria(BackoffPolicy.LINEAR, 1L, TimeUnit.MINUTES)
        .build();
WorkManager.getInstance(this).enqueue(request);

Android platformu, WorkManager'a ek olarak birkaç başka araç da sunar. gibi ağ görevlerini tamamlamak için verimli bir zaman çizelgesi oluşturmanıza yardımcı olur. tercih eder. Bu araçları kullanma hakkında daha fazla bilgi edinmek için Arka planda işleme rehberi.

Sunucu tarafından başlatılan istekleri optimize edin

Sunucu tarafından başlatılan istekler genellikle sunucu. Örneğin, en son haber makalelerini okumak için kullanılan bir uygulama kullanıcının kişiselleştirme tercihlerini alır.

Firebase Cloud Messaging ile sunucu güncellemeleri gönderin

Firebase Cloud Messaging (FCM) hafif bir bir sunucudan belirli bir uygulama örneğine veri iletmek için kullanılan mekanizma. Sunucunuz FCM'yi kullanarak belirli bir cihazda çalışan uygulamanızı bununla ilgili yeni veriler mevcut.

Uygulamanızın, sorgu yürütmek için sunucuya düzenli olarak pinglemesi gereken yoklamaya kıyasla yeni veri sağlarsanız, etkinliğe dayalı bu model sayesinde, uygulamanız ile yeni bir bağlantı oluşturabilirsiniz. yalnızca indirilecek veri olduğunu biliyorsa. Model, gereksiz bilgi sayısını en aza indirir. ve uygulamanızdaki bilgiler güncellenirken gecikmeyi azaltır.

FCM, kalıcı bir TCP/IP bağlantısı kullanılarak uygulanır. Böylece, kalıcı bağlantı sayısını artırır ve platformun bant genişliğini optimize etmesine olanak tanır ve pil ömrü üzerindeki etkiyi en aza indirmenize yardımcı olur.