Procesy w tle mogą pochłaniać dużo pamięci i baterii. Na przykład niejawna transmisja może uruchomić w tle wiele procesów, które zarejestrowały Wysłuchać ich, nawet jeśli te procesy nie przyniosą zbyt wiele korzyści. Może mieć mają duży wpływ na wydajność urządzenia i wrażenia użytkownika.
Aby rozwiązać ten problem, Android 7.0 (poziom interfejsu API 24) stosuje te zasady ograniczenia:
- Aplikacje kierowane na Androida 7.0 (poziom interfejsu API 24) i nowsze wersje nie otrzymują
CONNECTIVITY_ACTION
nadaje się, jeśli: określić odbiornik w pliku manifestu. Aplikacje będą nadal będą otrzymywaćCONNECTIVITY_ACTION
transmisję, jeśli zostaną zarejestrowane jegoBroadcastReceiver
zContext.registerReceiver()
a kontekst wciąż jest aktualny. - Aplikacje nie mogą wysyłać ani odbierać transmisji
ACTION_NEW_PICTURE
iACTION_NEW_VIDEO
. Ta optymalizacja dotyczy wszystkich aplikacji, nie tylko tych kierowanych na Androida 7.0 (poziom API 24).
Jeśli Twoja aplikacja używa któregoś z tych intencji, usuń zależności od nich
jak najszybciej, aby móc prawidłowo kierować reklamy na urządzenia z Androidem 7.0
lub wyższą. Platforma Androida udostępnia kilka rozwiązań, które pozwalają zminimalizować
na potrzeby tych niejawnych komunikatów. Na przykład: JobScheduler
i
nowy menedżer WorkManager udostępnia zaawansowane mechanizmy planowania sieci
w przypadku określonych warunków, na przykład połączenia z siecią bez pomiaru
są spełnione. Teraz możesz też używać JobScheduler
na zmiany dostawców treści. JobInfo
obiekty zawierają parametry, które JobScheduler
aby zaplanować zadanie. Po spełnieniu warunków zadania system
wykonuje to zadanie na zasobie JobService
Twojej aplikacji.
Na tej stronie dowiemy się, jak używać metod alternatywnych, takich jak
JobScheduler
, aby dostosować aplikację do nowych
ograniczeń.
Ograniczenia inicjowane przez użytkownika
Na stronie Wykorzystanie baterii w systemie użytkownik może wybierz jedną z następujących opcji:
- Bez ograniczeń: zezwala na pracę w tle, co może zużywać więcej baterii.
- Zoptymalizowane (ustawienie domyślne): optymalizacja działania aplikacji w tle, na podstawie interakcji użytkownika z aplikacją.
- Z ograniczonym dostępem:całkowicie uniemożliwia aplikacji działanie w tle. aplikacji; może nie działać zgodnie z oczekiwaniami.
Jeśli aplikacja wykazuje pewne działania opisane w sekcji Android Android Vitals, system może poprosić użytkownika o ograniczenie dostępu aplikacji do zasobów systemowych.
Jeśli system zauważy, że aplikacja zużywa zbyt dużo zasobów, i pozwala mu ograniczyć działania w aplikacji. Działania, które mogą spowodować wyświetlenie powiadomienia, to między innymi:
- Nadmierne blokady uśpienia: jedna częściowa blokada uśpienia zatrzymana na godzinę przy wyłączonym ekranie
- Nadmierne usługi w tle: jeśli aplikacja jest kierowana na interfejsy API niższe niż 26 i ma nadmierna liczba usług w tle
Dokładne ograniczenia są określane przez producenta urządzenia. Dla: na przykład w kompilacjach AOSP z Androidem 9 (poziom interfejsu API 28) lub nowszym działające w tle, które są objęte „ograniczonym” mają te elementy Ograniczenia:
- Nie udało się uruchomić usług działających na pierwszym planie
- Istniejące usługi na pierwszym planie zostaną usunięte
- Alarmy nie są wywoływane
- Zadania nie są wykonywane
Poza tym, jeśli aplikacja jest kierowana na Androida 13 (poziom interfejsu API 33) lub nowszego i jest
„z ograniczeniami” system nie przesyła komunikatu BOOT_COMPLETED
lub
komunikat LOCKED_BOOT_COMPLETED
do momentu uruchomienia aplikacji na innych urządzeniach
.
Konkretne ograniczenia są wymienione tutaj Ograniczenia dotyczące zarządzania energią.
Ograniczenia odbierania komunikatów o aktywności w sieci
Aplikacje kierowane na Androida 7.0 (poziom interfejsu API 24) nie otrzymują transmisji CONNECTIVITY_ACTION
, jeśli
zarejestrować się, aby otrzymać je w swoim pliku manifestu, oraz procesy zależne od tego
transmisja nie rozpocznie się. Może to stanowić problem w przypadku aplikacji, które chcą
nasłuchiwania zmian w sieci lub wykonywania działań zbiorczych w sieci, gdy
łączy się z siecią bez pomiaru. Kilka rozwiązań, które pozwalają obejść ten problem
na platformie Androida są już pewne ograniczenia, ale warto wybrać
zależy od tego,
co chcesz osiągnąć dzięki aplikacji.
Uwaga: BroadcastReceiver
zarejestrowana w
Context.registerReceiver()
będzie nadal odbierać te komunikaty, gdy aplikacja jest uruchomiona.
Zaplanuj zadania sieciowe w przypadku połączeń bez pomiaru użycia danych
Jeśli używasz klasy JobInfo.Builder
aby utworzyć obiekt JobInfo
, zastosuj metodę setRequiredNetworkType()
i przekaż JobInfo.NETWORK_TYPE_UNMETERED
jako parametr zadania. Następujący przykładowy kod
planuje uruchomienie usługi, gdy urządzenie łączy się z siecią bez pomiaru
sieci i trwa jej ładowanie:
Kotlin
const val MY_BACKGROUND_JOB = 0 ... fun scheduleJob(context: Context) { val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler val job = JobInfo.Builder( MY_BACKGROUND_JOB, ComponentName(context, MyJobService::class.java) ) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .build() jobScheduler.schedule(job) }
Java
public static final int MY_BACKGROUND_JOB = 0; ... public static void scheduleJob(Context context) { JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo job = new JobInfo.Builder( MY_BACKGROUND_JOB, new ComponentName(context, MyJobService.class)) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) .setRequiresCharging(true) .build(); js.schedule(job); }
Po spełnieniu warunków zadania aplikacja otrzymuje wywołanie zwrotne w celu jej uruchomienia
metody onStartJob()
w funkcji
określono JobService.class
. Więcej przykładów implementacji funkcji JobScheduler
znajdziesz w przykładowej aplikacji JoobScheduler.
Nową alternatywą dla JobScheduler jest WorkManager – interfejs API umożliwiający planowanie zadania w tle, które wymagają gwarantowane zakończenie niezależnie od tego, czy proces aplikacji jest w toku, czy nie. Menedżer roboczy wybiera odpowiedni sposób wykonania pracy (bezpośrednio w wątku w procesie aplikacji jako a także z JobScheduler, FirebaseJobDispatcher czy AlarmManagera) na podstawie takich czynników jak poziomu interfejsu API urządzenia. Oprócz tego WorkManager nie wymaga Usług Google Play i zapewnia kilka zaawansowanych funkcji, takich jak łączenie zadań ze sobą lub sprawdzanie ich stanu. Aby się uczyć Więcej informacji znajdziesz w sekcji WorkManager.
Monitorowanie połączeń sieciowych podczas działania aplikacji
Włączone aplikacje mogą nadal nasłuchiwać przez CONNECTIVITY_CHANGE
przy użyciu
zarejestrowano BroadcastReceiver
. Interfejs ConnectivityManager
API zapewnia jednak bardziej niezawodną metodę wysyłania żądań
wywołanie zwrotne tylko po spełnieniu określonych warunków sieciowych.
Obiekty NetworkRequest
definiują parametry funkcji
wywołanie zwrotne sieci (NetworkCapabilities
). Ty
tworzyć obiekty NetworkRequest
z klasą NetworkRequest.Builder
. registerNetworkCallback()
a następnie przekazuje obiekt NetworkRequest
do systemu. Kiedy
jeśli warunki sieciowe są spełnione, aplikacja otrzymuje wywołanie zwrotne w celu wykonania
Metoda onAvailable()
zdefiniowana w klasie ConnectivityManager.NetworkCallback
.
Aplikacja będzie otrzymywać wywołania zwrotne, dopóki nie zostanie zamknięta lub nie nawiąże połączenia.
unregisterNetworkCallback()
Ograniczenia dotyczące odbierania obrazów i transmisji wideo
Na Androidzie 7.0 (poziom interfejsu API 24) aplikacje nie mogą wysyłać ani odbierać transmisji ACTION_NEW_PICTURE
ani ACTION_NEW_VIDEO
. To ograniczenie pomaga
zmniejszać wpływ na wydajność i wygodę użytkowników, gdy konieczne jest
wybudzenia, żeby przetworzyć nowy obraz lub film. Android 7.0 (poziom API 24)
Rozszerza zakres JobInfo
i JobParameters
, aby zapewnić alternatywne rozwiązanie.
Aktywuj zadania w przypadku zmian identyfikatora URI treści
Aby aktywować zadania po zmianie identyfikatora URI treści, Android 7.0 (poziom API 24) rozszerzył
API JobInfo
za pomocą tych metod:
-
JobInfo.TriggerContentUri()
- Obejmuje parametry wymagane do aktywowania zadania po zmianie identyfikatora URI treści.
-
JobInfo.Builder.addTriggerContentUri()
-
Przekazuje obiekt
TriggerContentUri
doJobInfo
.ContentObserver
monitoruje zawarty w niej identyfikator URI treści. Jeśli z zadaniem powiązanych jest wiele obiektówTriggerContentUri
, system udostępni funkcję wywołanie zwrotne, nawet jeśli zgłasza zmianę tylko jednego z identyfikatorów URI treści. .
-
Dodaj flagę
TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS
do wyzwalać zadanie, jeśli zmienią się dowolne elementy podrzędne danego identyfikatora URI. Ta flaga odpowiada parametrowinotifyForDescendants
przekazanemu doregisterContentObserver()
.
Uwaga: TriggerContentUri()
nie można używać w tych krajach:
w połączeniu z wartością setPeriodic()
lub setPersisted()
. Aby stale monitorować zmiany w treści, zaplanuj nowy
JobInfo
przed zakończeniem obsługi ostatniego wywołania zwrotnego przez aplikację JobService
.
Ten przykładowy kod zaplanuje uruchomienie zadania, gdy system zgłosi
zmiana identyfikatora URI treści (MEDIA_URI
):
Kotlin
const val MY_BACKGROUND_JOB = 0 ... fun scheduleJob(context: Context) { val jobScheduler = context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler val job = JobInfo.Builder( MY_BACKGROUND_JOB, ComponentName(context, MediaContentJob::class.java) ) .addTriggerContentUri( JobInfo.TriggerContentUri( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS ) ) .build() jobScheduler.schedule(job) }
Java
public static final int MY_BACKGROUND_JOB = 0; ... public static void scheduleJob(Context context) { JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo.Builder builder = new JobInfo.Builder( MY_BACKGROUND_JOB, new ComponentName(context, MediaContentJob.class)); builder.addTriggerContentUri( new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS)); js.schedule(builder.build()); }
Gdy system zgłosi zmianę określonych identyfikatorów URI treści, aplikacja
otrzymuje wywołanie zwrotne, a obiekt JobParameters
jest
przekazano do onStartJob()
w komórce MediaContentJob.class
.
Sprawdzanie, które organizacje zajmujące się treścią aktywowały zadanie
Android 7.0 (poziom interfejsu API 24) rozszerza też JobParameters
na
pozwalają aplikacji otrzymywać przydatne informacje o urzędach certyfikacji,
i identyfikatory URI uruchomiły zadanie:
-
Uri[] getTriggeredContentUris()
-
Zwraca tablicę identyfikatorów URI, które aktywowały zadanie. Wartość to
null
, jeśli żaden z identyfikatorów URI nie uruchomił zadania (na przykład zadanie zostało spowodowane ze względu na termin lub inną przyczynę) albo liczbę zmienionych Identyfikatory URI mają więcej niż 50. -
String[] getTriggeredContentAuthorities()
-
Zwraca tablicę ciągów znaków urzędów treści, które aktywowały zadanie.
Jeśli zwrócona tablica nie jest wartością
null
, użyjgetTriggeredContentUris()
aby uzyskać szczegółowe informacje o zmienionych identyfikatorach URI.
Poniższy przykładowy kod zastępuje metodę JobService.onStartJob()
i
rejestruje urzędy treści i identyfikatory URI, które spowodowały uruchomienie zadania:
Kotlin
override fun onStartJob(params: JobParameters): Boolean { StringBuilder().apply { append("Media content has changed:\n") params.triggeredContentAuthorities?.also { authorities -> append("Authorities: ${authorities.joinToString(", ")}\n") append(params.triggeredContentUris?.joinToString("\n")) } ?: append("(No content)") Log.i(TAG, toString()) } return true }
Java
@Override public boolean onStartJob(JobParameters params) { StringBuilder sb = new StringBuilder(); sb.append("Media content has changed:\n"); if (params.getTriggeredContentAuthorities() != null) { sb.append("Authorities: "); boolean first = true; for (String auth : params.getTriggeredContentAuthorities()) { if (first) { first = false; } else { sb.append(", "); } sb.append(auth); } if (params.getTriggeredContentUris() != null) { for (Uri uri : params.getTriggeredContentUris()) { sb.append("\n"); sb.append(uri); } } } else { sb.append("(No content)"); } Log.i(TAG, sb.toString()); return true; }
Dalsza optymalizacja aplikacji
optymalizowanie aplikacji pod kątem działania na urządzeniach z małą ilością pamięci lub jej małą ilością pamięci; warunki, może poprawić wydajność i wygodę użytkowników. Usuwam zależności od usług w tle i niejawnie zarejestrowane w pliku manifestu odbiorniki mogą pomóc w lepszym działaniu aplikacji na takich urządzeniach. Chociaż Android 7.0 (poziom interfejsu API 24) podejmuje działania, by ograniczyć niektóre z tych problemów. zalecamy zoptymalizowanie aplikacji tak, aby działała bez użycia tych w tle.
Następujący Android Debug Bridge (ADB): umożliwiają przetestowanie działania aplikacji przy wyłączonych procesach w tle:
- Symulowanie warunków, w których niejawne transmisje i usługi w tle są niedostępne, wpisz następujące polecenie:
-
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore
- Aby ponownie włączyć niejawne transmisje i usługi w tle, wpisz to polecenie:
-
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
- Możesz symulować umieszczanie aplikacji przez użytkownika jako „objęte ograniczeniami” stan dla wykorzystanie baterii w tle. To ustawienie uniemożliwia uruchamianie aplikacji w tle. Aby to zrobić, uruchom następujące polecenie w oknie terminala:
-
$ adb shell cmd appops set <PACKAGE_NAME> RUN_ANY_IN_BACKGROUND deny