Procesy w tle mogą zużywać dużo pamięci i baterii. Na przykład komunikat ogólny może uruchomić wiele procesów w tle, które zostały zarejestrowane do jego nasłuchiwania, nawet jeśli te procesy nie wykonują zbyt wiele pracy. Może to mieć znaczący wpływ zarówno na wydajność urządzenia, jak i na wrażenia użytkownika.
Aby uniknąć ograniczeń systemowych, upewnij się, że używasz odpowiedniego interfejsu API do zadania w tle. Dokumentacja Omówienie zadań w tle pomoże Ci wybrać interfejs API odpowiedni do Twoich potrzeb.
Ograniczenia inicjowane przez użytkownika
Jeśli aplikacja wykazuje niektóre z niewłaściwych działań opisanych w Android Vitals, system prosi użytkownika o ograniczenie jej dostępu do zasobów systemowych.
Jeśli system zauważy, że aplikacja zużywa nadmierne zasoby, powiadomi o tym użytkownika i da mu możliwość ograniczenia jej działań. Zachowania, które mogą spowodować wyświetlenie powiadomienia, to m.in.:
- Zbyt częste blokady uśpienia: 1 częściowa blokada uśpienia utrzymywana przez godzinę, gdy ekran jest wyłączony.
- Zbyt wiele usług w tle: jeśli aplikacja jest kierowana na interfejsy API na poziomie niższym niż 26 i ma zbyt wiele usług w tle.
Dokładne ograniczenia są określane przez producenta urządzenia. Na przykład w kompilacjach AOSP aplikacje z ograniczonym dostępem nie mogą uruchamiać zadań, wywoływać alarmów ani korzystać z sieci, chyba że działają na pierwszym planie.
Ograniczenia dotyczące odbierania transmisji aktywności sieciowej
Aplikacje nie otrzymują komunikatów CONNECTIVITY_ACTION, jeśli zarejestrują się, aby je otrzymywać w pliku manifestu, a procesy, które zależą od tego komunikatu, nie zostaną uruchomione. Może to stanowić problem w przypadku aplikacji, które chcą nasłuchiwać zmian w sieci lub wykonywać zbiorcze działania sieciowe, gdy urządzenie łączy się z siecią bez taryfowego rozliczania danych. W platformie Androida istnieje już kilka rozwiązań, które pozwalają obejść to ograniczenie, ale wybór odpowiedniego zależy od tego, co chcesz osiągnąć za pomocą aplikacji.
Planowanie pracy na połączeniach bez pomiaru
Podczas tworzenia WorkRequest dodaj NetworkType.UNMETERED Constraint.
fun scheduleWork(context: Context) { val workManager = WorkManager.getInstance(context) val workRequest = OneTimeWorkRequestBuilder<MyWorker>() .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.UNMETERED) .build() ) .build() workManager.enqueue(workRequest) }
Gdy warunki zostaną spełnione, aplikacja otrzyma wywołanie zwrotne, aby uruchomić metodę doWork() w określonej klasie Worker.
monitorowanie połączenia sieciowego podczas działania aplikacji;
Uruchomione aplikacje mogą nadal nasłuchiwać CONNECTIVITY_CHANGE za pomocą zarejestrowanego BroadcastReceiver. Interfejs API ConnectivityManager zapewnia jednak bardziej niezawodną metodę żądania wywołania zwrotnego tylko wtedy, gdy spełnione są określone warunki sieciowe.
Obiekty NetworkRequest definiują parametry wywołania zwrotnego sieci w odniesieniu do NetworkCapabilities. Obiekty NetworkRequest tworzysz za pomocą klasy NetworkRequest.Builder. registerNetworkCallback, a następnie przekazuje obiekt NetworkRequest do systemu. Gdy warunki sieciowe zostaną spełnione, aplikacja otrzyma wywołanie zwrotne, aby wykonać metodę onAvailable() zdefiniowaną w klasie ConnectivityManager.NetworkCallback.
Aplikacja będzie otrzymywać wywołania zwrotne, dopóki nie zostanie zamknięta lub nie wywoła metody unregisterNetworkCallback().
Ograniczenia dotyczące otrzymywania transmisji obrazów i filmów
Aplikacje nie mogą wysyłać ani odbierać komunikatów ACTION_NEW_PICTURE ani ACTION_NEW_VIDEO. To ograniczenie pomaga zmniejszyć wpływ na wydajność i wrażenia użytkownika, gdy kilka aplikacji musi się wybudzić, aby przetworzyć nowy obraz lub film.
Określanie, które urzędy ds. treści wywołały działanie
WorkerParameters umożliwia aplikacji otrzymywanie przydatnych informacji o tym, jakie urzędy treści i identyfikatory URI wywołały zadanie:
List<Uri> getTriggeredContentUris()
Zwraca listę identyfikatorów URI, które wywołały zadanie. To pole jest puste, jeśli żadne identyfikatory URI nie wywołały zadania (np. zadanie zostało wywołane z powodu terminu lub z innego powodu) lub liczba zmienionych identyfikatorów URI jest większa niż 50.
List<String> getTriggeredContentAuthorities()
Zwraca listę ciągów znaków z organami ds. treści, które wywołały zadanie. Jeśli zwrócona lista nie jest pusta, użyj getTriggeredContentUris(), aby pobrać szczegółowe informacje o tym, które identyfikatory URI uległy zmianie.
Poniższy przykładowy kod zastępuje metodę CoroutineWorker.doWork() i rejestruje urzędy treści oraz identyfikatory URI, które wywołały zadanie:
class MyWorker( appContext: Context, private val params: WorkerParameters ) : CoroutineWorker(appContext, params) { override suspend fun doWork(): Result { StringBuilder().apply { append("Media content has changed:\n") params.triggeredContentAuthorities .takeIf { it.isNotEmpty() } ?.let { authorities -> append("Authorities: ${authorities.joinToString(", ")}\n") append(params.triggeredContentUris.joinToString("\n")) } ?: append("(No content)") Log.i(TAG, toString()) } return Result.success() } }
Testowanie aplikacji z ograniczeniami systemowymi
Optymalizacja aplikacji pod kątem działania na urządzeniach z małą ilością pamięci lub w warunkach małej ilości pamięci może poprawić wydajność i wygodę użytkowników. Usunięcie zależności od usług w tle i odbiorników komunikatów ogólnych zarejestrowanych w pliku manifestu może poprawić działanie aplikacji na takich urządzeniach. Zalecamy zoptymalizowanie aplikacji tak, aby działała bez użycia tych procesów w tle.
Niektóre dodatkowe polecenia Android Debug Bridge (ADB) mogą pomóc w testowaniu działania aplikacji z wyłączonymi procesami w tle:
Aby zasymulować warunki, w których komunikaty ogólne i usługi w tle są niedostępne, wpisz to polecenie:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignoreAby ponownie włączyć komunikaty ogólne i usługi w tle, wpisz to polecenie:
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
Dalsza optymalizacja aplikacji
Inne dobre sposoby optymalizacji działania zadań w tle znajdziesz w dokumentacji dotyczącej optymalizacji wykorzystania baterii w przypadku interfejsów API do planowania zadań.