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 go zoptymalizować, musisz go mierzyć i określać jego źródło. Żądania sieci mogą pochodzić bezpośrednio od użytkownika, z kodu aplikacji lub od serwera, który komunikuje się z aplikacją.

Z tego tematu dowiesz się, jak monitorować i kategoryzować ruch sieciowy oraz jak identyfikować i rozwiązywać problemy.

Monitorowanie żądań za pomocą narzędzia Network Profiler

Aby śledzić żądania sieciowe aplikacji, użyj Profilatora sieci. Możesz sprawdzać, jak i kiedy aplikacja przesyła dane, oraz odpowiednio optymalizować kod źródłowy.



Rysunek 1. śledzenie ruchu w sieci, Wzór ruchu w sieci sugeruje, że można znacznie zwiększyć wydajność, pobierając żądania w ramach wstępnego pobierania lub grupowania przesyłanych danych.

Dzięki monitorowaniu częstotliwości przesyłania danych i ich ilości podczas każdego połączenia możesz określić obszary aplikacji, które można zoptymalizować pod kątem oszczędzania baterii. Zazwyczaj szukasz krótkich pików, które mogą być opóźnione.

Aby lepiej zidentyfikować przyczynę wzrostu transferu, interfejs Traffic Stats API umożliwia oznaczanie tagami transferów danych pochodzących z gniazda w ramach danego wątku za pomocą elementu TrafficStats.setThreadStatsTag(). Wywołanie tej funkcji nie powoduje automatycznego otagowania całego ruchu w danym wątku; tagi muszą zostać zastosowane do gniazd.

Po ustawieniu etykiety wątku możesz ręcznie oznaczać i usuwać etykiety poszczególnych gniazd za pomocą TrafficStats.tagSocket()TrafficStats.untagSocket(). Tag jest też stosowany, jeśli gniazdo jest otwarte na wątku lub jeśli gniazdo serwera akceptuje połączenie.

Równoczesny dostęp do tego samego gniazda przez wiele wątków będzie używać tagu gniazda, który był używany w momencie wysyłania lub odbierania pakietów sieciowych (co może być inne niż w momencie zapisywania lub odczytywania danych przez użytkownika z powodu buforowania i przesyłania ponownie).

Możesz na przykład zdefiniować stałe, które będą reprezentować różne typy ruchu sieciowego, 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;

Możesz wtedy odpowiednio oznaczać żądania sieci:

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 oznacza gniazda na podstawie bieżącej wartości TrafficStats.getThreadStatsTag(). Biblioteka oznacza i odznacza też gniazda podczas ich recyklingu w grupach keep-alive, jak pokazano w tym przykładzie kodu:

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

Gdy analizujesz ruch w sieci generowany przez aplikację, musisz znać źródło tego ruchu, aby móc go odpowiednio optymalizować. Częste działanie w sieci generowane przez aplikację może być całkowicie odpowiednie, jeśli jest ono reakcją na działania użytkownika, ale może być też całkowicie nieodpowiednie, jeśli aplikacja nie jest na pierwszym planie lub jeśli urządzenie jest w kieszeni lub torebce.

Analizowanie ruchu inicjowanego przez użytkownika

Ruch sieciowy wywołany przez użytkownika może być efektywnie grupowany podczas wykonywania przez niego określonego zadania w aplikacji lub rozłożony nierównomiernie, gdy użytkownik prosi o dodatkowe informacje, których potrzebuje Twoja aplikacja. Celem analizowania ruchu w sieci inicjowanego przez użytkownika jest wyszukiwanie w czasie wzorców częstego korzystania z sieci i próba zmniejszenia ich częstotliwości przez grupowanie żądań.

Nieprzewidywalność żądań użytkowników utrudnia optymalizację tego typu wykorzystania sieci w aplikacji. Ponadto użytkownicy oczekują 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. Ogólnie rzecz biorąc, szybsza reakcja na użytkownika jest ważniejsza od efektywnego wykorzystania sieci, gdy użytkownik bezpośrednio wchodzi w interakcję z aplikacją.

Zalecenia dotyczące optymalizacji ruchu wywołanego przez użytkownika znajdziesz w artykule Optymalizacja żądań wywoływanych przez użytkownika.

Analizowanie ruchu wywołanego przez aplikację

Ruch sieciowy wywoływany przez aplikację to zwykle obszar, w którym możesz mieć znaczący wpływ na efektywne wykorzystanie przepustowości sieci. Podczas analizowania aktywności w sieci Twojej aplikacji poszukaj okresów bezczynności i sprawdź, czy można je wydłużyć. Jeśli zauważysz w swojej aplikacji wzorce stałego dostępu do sieci, spróbuj grupować ten ruch, aby umożliwić radioodbiornikom na urządzeniu przełączenie się z pomiędzy okresami aktywności w tryb niskiego zużycia energii.

Rekomendacje dotyczące optymalizacji ruchu wywołanego przez aplikację znajdziesz w artykule Optymalizacja żądań wywołanych przez aplikację.

Analizowanie ruchu inicjowanego przez serwer

Aktywność sieciowa inicjowana przez serwery komunikujące się z Twoją aplikacją to też zazwyczaj 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 powiadomić aplikację działającą na konkretnym urządzeniu, że są dla niej dostępne nowe dane.

Zalecenia dotyczące optymalizacji ruchu wywoływanego przez serwer znajdziesz w artykule Optymalizacja żądań wywoływanych przez serwer.

Wykorzystanie narzędzia Battery Historian do wizualizacji wpływu ruchu sieciowego

Historia baterii to narzędzie, które wizualizuje zużycie baterii urządzenia w danym okresie. Za pomocą tego narzędzia możesz analizować wpływ aktywności w sieci na zużycie baterii. Na przykład Battery Historian może pokazać, czy aplikacja korzysta z radia komórkowego częściej niż się spodziewasz. Więcej informacji o używaniu Battery Historian znajdziesz w artykule Profilowanie wykorzystania baterii za pomocą Batterystats i Battery Historian.