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. Może to mieć znaczny wpływ na wydajność urządzenia i wygodę użytkowników.
Aby rozwiązać ten problem, w Androidzie 7.0 (poziom interfejsu API 24) obowiązują te 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 nadal będą otrzymywać transmisjeCONNECTIVITY_ACTION
, jeśliBroadcastReceiver
zostanie zarejestrowany wContext.registerReceiver()
, a ten kontekst nadal będzie ważny. - Aplikacje nie mogą wysyłać ani odbierać transmisji
ACTION_NEW_PICTURE
aniACTION_NEW_VIDEO
. Ta optymalizacja dotyczy wszystkich aplikacji, a nie tylko tych kierowanych na Androida 7.0 (poziom API 24).
Jeśli Twoja aplikacja używa któregoś z tych intencji, jak najszybciej usuń te zależności, aby móc odpowiednio kierować reklamy na urządzenia z Androidem 7.0 lub nowszym. Platforma Android oferuje kilka rozwiązań, które ograniczają potrzebę korzystania z tych niejawnych transmisji. Na przykład JobScheduler
i nowy WorkManager zapewniają niezawodne mechanizmy do planowania operacji sieciowych, gdy spełnione są określone warunki, takie jak połączenie z siecią bez limitu danych. Teraz możesz też używać JobScheduler
na zmiany dostawców treści. JobInfo
obiekty zawierają parametry, które JobScheduler
aby zaplanować zadanie. Gdy warunki zadania zostaną spełnione, system wykona to zadanie w Twojej aplikacji JobService
.
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 Użycie baterii w ustawieniach systemu użytkownik może wybrać jedną z tych opcji:
- Nieograniczone: zezwalaj na wszystkie działania w tle, które mogą zużywać więcej baterii.
- Zoptymalizowana (domyślnie): optymalizuje działanie aplikacji w tle na podstawie interakcji użytkownika z aplikacją.
- Ograniczone: 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 nadmierne zasoby, powiadomi użytkownika i zaoferuje mu możliwość ograniczenia działań aplikacji. Działania, które mogą spowodować wyświetlenie powiadomienia, to między innymi:
- Zbyt wiele blokad uśpienia: 1 częściowa blokada uśpienia utrzymana przez godzinę, gdy ekran jest wyłączony
- 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 można uruchomić usług na pierwszym planie
- Istniejące usługi na pierwszym planie zostaną usunięte
- Alarmy nie są aktywowane
- Zadania nie są wykonywane
Jeśli aplikacja jest kierowana na Androida 13 (API na poziomie 33) lub nowszego i jest w stanie „ograniczony”, system nie dostarcza transmisji BOOT_COMPLETED
ani LOCKED_BOOT_COMPLETED
, dopóki aplikacja nie zostanie uruchomiona z innych powodów.
Konkretne ograniczenia są wymienione tutaj Ograniczenia dotyczące zarządzania energią.
Ograniczenia dotyczące odbierania transmisji aktywności 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 dla aplikacji, które chcą nasłuchiwać zmian w sieci lub wykonywać zbiorcze działania sieciowe, gdy urządzenie łączy się z siecią bez limitu. Kilka rozwiązań, które pomagają ominąć 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.
Planowanie zadań sieciowych na połączeniach bezpłatnych
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:
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) }
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, który umożliwia planowanie zadań w tle, które wymagają gwarantowanego ukończenia, niezależnie od tego, czy proces aplikacji jest uruchomiony. Menedżer pracy 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łączenia z internetem podczas działania aplikacji
Uruchomione aplikacje mogą nadal nasłuchiwać CONNECTIVITY_CHANGE
z zarejestrowanym 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 wywołania zwrotnego sieci w terminach 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 wywoła funkcji unregisterNetworkCallback()
.
Ograniczenia dotyczące odbierania obrazów i transmisji wideo
W Androidzie 7.0 (interfejs API na poziomie 24) aplikacje nie mogą wysyłać ani odbierać transmisji ACTION_NEW_PICTURE
ani ACTION_NEW_VIDEO
. To ograniczenie pomaga ograniczyć wpływ na wydajność i wrażenia użytkownika, gdy kilka aplikacji musi się aktywować, aby przetworzyć nowy obraz lub film. Android 7.0 (poziom interfejsu API 24) rozszerza 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 zakapsułowany identyfikator URI treści. Jeśli z zadaniem powiązanych jest wiele obiektówTriggerContentUri
, system wywołuje funkcję zwrotną, nawet jeśli zgłosi 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. Ten parametr odpowiada parametrowinotifyForDescendants
przekazanemu do funkcjiregisterContentObserver()
.
Uwaga: TriggerContentUri()
nie można używać w tych krajach:
w połączeniu z wartością setPeriodic()
lub setPersisted()
. Aby stale sprawdzać, czy nie nastąpiły zmiany treści, zaplanuj nowe JobInfo
, zanim funkcja JobService
w aplikacji zakończy obsługę ostatniego wywołania zwrotnego.
Poniższy przykładowy kod powoduje uruchomienie zadania, gdy system zgłosi zmianę identyfikatora URI treści, MEDIA_URI
:
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) }
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ę w wybranych identyfikatorach URI treści, Twoja aplikacja otrzyma wywołanie zwrotne, a obiekt JobParameters
zostanie przekazany metodzie onStartJob()
w MediaContentJob.class
.
Określanie, które instytucje zajmujące się treściami wywołał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 wywołały zadanie. Będzie to
null
, jeśli żadne adresy URI nie zostały uruchomione (na przykład zadanie zostało uruchomione z powodu terminu lub z innego powodu) albo jeśli liczba zmienionych adresów URI jest większa niż 50. -
String[] getTriggeredContentAuthorities()
- Zwraca tablicę ciągów znaków z autorytetami treści, które wywołał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:
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 }
@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:
- Aby symulować warunki, w których transmisje niejawne i usługi w tle są niedostępne, wpisz to polecenie:
-
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore
- Aby ponownie włączyć transmisje i usługi w tle, wpisz to polecenie:
-
$ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow
- Możesz symulować sytuację, w której użytkownik ustawia stan „Ograniczone” dla wykorzystania baterii w tle w Twojej aplikacji. To ustawienie uniemożliwia uruchamianie aplikacji w tle. Aby to zrobić, uruchom w oknie terminala to polecenie:
-
$ adb shell cmd appops set <PACKAGE_NAME> RUN_ANY_IN_BACKGROUND deny