Rozwiązywanie problemów z siecią

Ruch sieciowy generowany przez aplikację może mieć znaczący wpływ na czas pracy baterii urządzenia. Aby zoptymalizować ten ruch, musisz go zmierzyć i określić jego źródło. Żądania sieciowe mogą pochodzić bezpośrednio z działania użytkownika, z kodu Twojej aplikacji lub z serwera komunikującego się z aplikacją.

Z tego artykułu dowiesz się, jak monitorować i kategoryzować ruch w sieci oraz jak identyfikować i rozwiązywać problemy.

Monitorowanie żądań za pomocą profilera sieci

Użyj profilera sieci, aby śledzić żądania sieciowe aplikacji. Możesz monitorować, jak i kiedy aplikacja przesyła dane, oraz odpowiednio optymalizować kod źródłowy.



Rysunek 1. śledzenie ruchu w sieci, Wzorzec ruchu w sieci sugeruje, że efektywność można znacznie zwiększyć, wstępnie pobierając żądania lub łącząc przesyłane pliki.

Monitorując częstotliwość przesyłania danych i ilość danych przesyłanych podczas każdego połączenia, możesz określić obszary aplikacji, w których można zwiększyć oszczędność baterii. Zwykle szukasz krótkich skoków, które mogą być opóźnione.

Aby lepiej identyfikować przyczyny skoków w przesyłaniu danych, interfejs Traffic Stats API umożliwia oznaczanie przesyłania danych z gniazda w danym wątku za pomocą TrafficStats.setThreadStatsTag(). Wywołanie tej funkcji nie powoduje automatycznego otagowania całego ruchu w określonym wątku. Tagi muszą być stosowane do gniazd.

Po ustawieniu tagu wątku możesz ręcznie oznaczać i usuwać oznaczenia poszczególnych gniazd za pomocą symboli TrafficStats.tagSocket()TrafficStats.untagSocket(). Tag jest też stosowany, gdy w wątku zostanie otwarte gniazdo lub gdy gniazdo serwera zaakceptuje połączenie.

Współbieżny dostęp do tego samego gniazda przez wiele wątków będzie używać tagu, który gniazdo miało w momencie wysyłania lub odbierania pakietów sieciowych (może się on różnić od tagu, który był używany, gdy użytkownik zapisywał lub odczytywał dane, ze względu na buforowanie i ponowne przesyłanie).

Możesz na przykład zdefiniować stałe reprezentujące różne typy ruchu w sieci, jak pokazano w tym przykładzie kodu:

Kotlin

const val USER_INITIATED = 0x1000
const val APP_INITIATED = 0x2000
const val SERVER_INITIATED = 0x3000

Java

public static final int USER_INITIATED = 0x1000;
public static final int APP_INITIATED = 0x2000;
public static final int SERVER_INITIATED = 0x3000;

Następnie możesz odpowiednio oznaczyć żądania sieciowe:

Kotlin

TrafficStats.setThreadStatsTag(USER_INITIATED)
TrafficStats.tagSocket(outputSocket)
// Transfer data using socket
TrafficStats.untagSocket(outputSocket)

Java

TrafficStats.setThreadStatsTag(USER_INITIATED);
TrafficStats.tagSocket(outputSocket);
// Transfer data using socket
TrafficStats.untagSocket(outputSocket);

Biblioteka HttpURLConnection automatycznie taguje gniazda na podstawie bieżącej wartości TrafficStats.getThreadStatsTag(). Biblioteka taguje i usuwa tagi z gniazd, gdy są one ponownie wykorzystywane w puli połączeń keep-alive, jak pokazano w tym przykładowym kodzie:

Kotlin

class IdentifyTransferSpikeTask {
    @WorkerThread
    fun request(url: String) {
        TrafficStats.setThreadStatsTag(APP_INITIATED)
        // Make network request using HttpURLConnection.connect()
        ...
        TrafficStats.clearThreadStatsTag()
    }
}

Java

public class IdentifyTransferSpikeTask {
    @WorkerThread
    public void request(String url) {
        TrafficStats.setThreadStatsTag(APP_INITIATED);
        // Make network request using HttpURLConnection.connect()
        ...
        TrafficStats.clearThreadStatsTag();
    }
}

Analizowanie typów ruchu sieciowego

Analizując ruch w sieci generowany przez aplikację, musisz znać jego źródło, aby móc go odpowiednio zoptymalizować. Częsta aktywność sieciowa generowana przez aplikację może być w pełni uzasadniona, jeśli jest odpowiedzią na działania użytkownika, ale zupełnie nieodpowiednia, jeśli aplikacja nie jest na pierwszym planie lub urządzenie znajduje się w kieszeni lub torebce.

Analizowanie ruchu inicjowanego przez użytkowników

Ruch sieciowy inicjowany przez użytkownika może być efektywnie grupowany, gdy użytkownik wykonuje określone zadanie w aplikacji, lub rozproszony nierównomiernie, gdy użytkownik prosi o dodatkowe informacje, których aplikacja potrzebuje. Analizując ruch sieciowy inicjowany przez użytkowników, szukaj wzorców częstego korzystania z sieci w czasie i staraj się zmniejszyć ich częstotliwość, grupując żądania.

Nieprzewidywalność żądań użytkowników utrudnia optymalizację tego typu wykorzystania sieci w aplikacji. Użytkownicy oczekują też szybkich odpowiedzi, gdy aktywnie korzystają z aplikacji, więc opóźnianie żądań w celu zwiększenia wydajności może pogorszyć wrażenia użytkowników. Gdy użytkownik bezpośrednio korzysta z aplikacji, priorytetem powinna być szybka reakcja na jego działania, a nie efektywne wykorzystanie sieci.

Rekomendacje dotyczące optymalizacji ruchu inicjowanego przez użytkowników znajdziesz w artykule Optymalizowanie żądań inicjowanych przez użytkowników.

Analizowanie ruchu inicjowanego przez aplikacje

Ruch sieciowy inicjowany przez aplikację to zwykle obszar, w którym możesz mieć znaczący wpływ na efektywne wykorzystanie przepustowości sieci. Analizując aktywność sieciową aplikacji, poszukaj okresów bezczynności i sprawdź, czy można je wydłużyć. Jeśli zauważysz, że aplikacja regularnie uzyskuje dostęp do sieci, spróbuj grupować ten ruch, aby radio urządzenia mogło przełączać się z powrotem w tryb niskiego zużycia energii między okresami aktywności.

Rekomendacje dotyczące optymalizacji ruchu inicjowanego przez aplikacje znajdziesz w artykule Optymalizacja żądań inicjowanych przez aplikacje.

Analizowanie ruchu inicjowanego przez serwer

Aktywność sieciowa inicjowana przez serwery komunikujące się z aplikacją to również obszar, w którym możesz mieć znaczący wpływ na efektywne wykorzystanie przepustowości sieci. Komunikacja w chmurze Firebase (FCM) to lekki mechanizm służący do przesyłania danych z serwera do konkretnej instancji aplikacji. Za pomocą FCM serwer może powiadamiać aplikację działającą na konkretnym urządzeniu o dostępności nowych danych.

Rekomendacje dotyczące optymalizacji ruchu inicjowanego przez serwer znajdziesz w artykule Optymalizowanie żądań inicjowanych przez serwer.

Używanie narzędzia Battery Historian do wizualizacji wpływu ruchu sieciowego

Battery Historian to narzędzie, które wizualizuje zużycie baterii urządzenia w określonym czasie. Za pomocą tego narzędzia możesz analizować, jak aktywność sieciowa wpływa na zużycie baterii. Na przykład Battery Historian może pokazać, czy Twoja aplikacja korzysta z radia komórkowego częściej niż oczekujesz. Więcej informacji o korzystaniu z narzędzia Battery Historian znajdziesz w artykule Profilowanie wykorzystania baterii za pomocą narzędzi Batterystats i Battery Historian.