ANR'ler

Bir Android uygulamasının kullanıcı arayüzü iş parçacığı çok uzun süre engellendiğinde "Uygulama Yanıt Vermiyor" (ANR) hatası tetiklenir. Uygulama ön plandaysa sistem kullanıcıya Şekil 1'de gösterildiği gibi bir iletişim kutusu görüntüler. ANR iletişim kutusu, kullanıcıya uygulamadan zorla çıkma fırsatı verir.

Şekil 1. Kullanıcıya gösterilen ANR iletişim kutusu

Şekil 1. Kullanıcıya gösterilen ANR iletişim kutusu

Uygulamanın kullanıcı arayüzünü güncellemekten sorumlu olan ana iş parçacığı, kullanıcı girişi etkinliklerini veya çizimini işleyemediğinden ANR'ler bir sorun teşkil eder. Bu da kullanıcının hayal kırıklığına uğramasına neden olur. Uygulamanın ana iş parçacığı hakkında daha fazla bilgi için İşlemler ve ileti dizileri bölümüne bakın.

Aşağıdaki koşullardan biri gerçekleştiğinde uygulamanız için bir ANR tetiklenir:

  • Giriş gönderme zaman aşımına uğradı: Uygulamanız bir giriş etkinliğine (ör. tuşa basma veya ekrana dokunma) 5 saniye içinde yanıt vermediyse.
  • Yürütme hizmeti: Uygulamanız tarafından beyan edilen bir hizmet, Service.onCreate() ve Service.onStartCommand()/Service.onBind() yürütmeyi birkaç saniye içinde tamamlayamazsa.
  • Service.startForeground() çağrılmadı: Uygulamanız ön planda yeni bir hizmet başlatmak için Context.startForegroundService() kullanıyorsa ancak hizmet 5 saniye içinde startForeground() yöntemini çağırmazsa.
  • Niyet yayını: Bir BroadcastReceiver belirli bir süre içinde yürütmeyi tamamlamamışsa. Uygulamanın ön planda herhangi bir etkinliği varsa bu zaman aşımı 5 saniyedir.
  • JobScheduler etkileşimleri: Bir JobService birkaç saniye içinde JobService.onStartJob() veya JobService.onStopJob() ürününden geri dönmezse veya kullanıcı tarafından başlatılan bir iş başlarsa ve uygulamanız JobService.onStartJob() çağrıldıktan sonra birkaç saniye içinde JobService.setNotification() çağrısını yapmazsa. Android 13 ve önceki sürümleri hedefleyen uygulamalarda ANR'ler sessizdir ve uygulamaya bildirilmez. Android 14 ve sonraki sürümleri hedefleyen uygulamalarda ANR'ler açıkça anlaşılır ve uygulamaya bildirilir.

Uygulamanızda ANR deneyimi yaşanıyorsa sorunu teşhis edip düzeltmek için bu makaledeki bilgilerden yararlanabilirsiniz.

Sorunu tespit edin

Uygulamanızı zaten yayınladıysanız uygulamanızın ANR'leri ile ilgili bilgileri görmek için Android vitals'ı kullanabilirsiniz. ANR'leri tespit etmek için sahadaki diğer araçları kullanabilirsiniz. Ancak 3. taraf araçların, Android vitals'ın aksine Android'in eski sürümlerindeki (Android 10 ve önceki sürümler) ANR'leri bildiremeyeceğini unutmayın.

Android vitals

Android vitals, uygulamanızın ANR oranını izlemenize ve iyileştirmenize yardımcı olabilir. Android vitals çeşitli ANR oranlarını ölçer:

  • ANR oranı: Günlük etkin kullanıcılarınız arasında, herhangi bir türde ANR yaşayanların yüzdesidir.
  • Kullanıcı tarafından algılanan ANR oranı: Günlük etkin kullanıcılarınız arasında, en az bir kullanıcı tarafından algılanan ANR yaşayanların yüzdesidir. Şu anda yalnızca Input dispatching timed out türündeki ANR'ler kullanıcı tarafından algılanan olarak kabul edilmektedir.
  • Çoklu ANR oranı: Günlük etkin kullanıcılarınız arasında en az iki ANR yaşayanların yüzdesidir.

Günlük etkin kullanıcı, uygulamanızı tek bir gün içinde tek bir cihazda ve potansiyel olarak birden fazla oturumda kullanan tekil bir kullanıcıdır. Bir kullanıcı aynı günde uygulamanızı birden fazla cihazda kullanırsa her cihaz o günün etkin kullanıcı sayısına eklenir. Birden fazla kullanıcı tek bir gün içinde aynı cihazı kullanırsa bu, tek bir etkin kullanıcı olarak sayılır.

Kullanıcı tarafından algılanan ANR oranı önemli bir metriktir. Yani Google Play'de uygulamanızın keşfedilebilirliğini etkiler. Bu metriğin saydığı ANR'lerin her zaman kullanıcılar uygulamayla etkileşim halindeyken gerçekleşerek çok fazla aksamaya yol açması, bu metriği önemli kılar.

Play bu metrikte iki kötü davranış eşiği belirlemiştir:

  • Genel kötü davranış eşiği: Tüm cihaz modellerinde, günlük etkin kullanıcıların en az% 0,47'si, kullanıcı tarafından algılanan ANR yaşamıştır.
  • Cihaz bazında kötü davranış eşiği: Günlük kullanıcıların en az% 8'i tek bir cihaz modeli için, kullanıcı tarafından algılanan ANR yaşamıştır.

Genel kötü davranış eşiğini aşan uygulamaların tüm cihazlarda bulunabilirliği azalabilir. Uygulamanız bazı cihazlarda cihaz başına kötü davranış eşiğini aşarsa bu cihazlardaki bulunabilirliği azalabilir ve mağaza girişinizde bir uyarı gösterilebilir.

Uygulamanız aşırı sayıda ANR gösterdiğinde Android vitals, Play Console aracılığıyla sizi uyarabilir.

Google Play'in Android vitals verilerini nasıl topladığı hakkında bilgi için Play Console belgelerine bakın.

ANR'leri teşhis etme

ANR'leri teşhis ederken yaygın olarak bakılacak bazı kalıplar vardır:

  • Uygulama, ana iş parçacığında G/Ç içeren yavaş işlemler gerçekleştiriyor.
  • Uygulama, ana iş parçacığında uzun bir hesaplama yapıyor.
  • Ana iş parçacığı başka bir işleme eşzamanlı bir bağlayıcı çağrısı yapıyor ve diğer işlemin geri dönüşü uzun sürüyor.
  • Ana iş parçacığı, başka bir iş parçacığında gerçekleşen uzun bir işlem için senkronize edilmiş bir blok beklenirken engellenir.
  • Ana iş parçacığı, işleminizde veya bir bağlayıcı çağrısı aracılığıyla başka bir iş parçacığı ile kilitlenmededir. Ana iş parçacığı sadece uzun bir işlemin tamamlanmasını beklemekle kalmıyor, aynı zamanda bir kilitlenmede de bulunuyor. Daha fazla bilgi için Wikipedia'daki Kilitlenme bölümüne bakın.

Aşağıdaki teknikler, ANR'lerinizin nedenini belirlemenize yardımcı olabilir.

Sağlık İstatistikleri

HealthStats toplam kullanıcı ve sistem süresini, CPU saatini, ağ, radyo istatistiklerini, ekran açılma/kapanma zamanını ve uyandırma alarmlarını yakalayarak uygulamanın sağlık durumu hakkında metrikler sağlar. Bu, genel CPU kullanımını ve pil tüketimini ölçmeye yardımcı olabilir.

Hata ayıkla

Debug, uygulamalardaki olumsuzluk ve gecikmeleri belirlemek için izleme ve ayırma sayıları dahil olmak üzere geliştirme sırasında Android uygulamalarının denetlenmesine yardımcı olur. Ayrıca, çalışma zamanı ve yerel bellek sayaçlarının yanı sıra belirli bir işlemin bellek ayak izini tanımlamaya yardımcı olabilecek bellek metrikleri edinmek için Debug öğesini de kullanabilirsiniz.

UygulamaÇıkış Bilgisi

ApplicationExitInfo, Android 11 (API düzeyi 30) veya sonraki sürümlerde kullanılabilir ve uygulamadan çıkma nedeni hakkında bilgi sağlar. Buna ANR'ler, düşük bellek, uygulama kilitlenmeleri, aşırı CPU kullanımı, kullanıcı kesintileri, sistem kesintileri veya çalışma zamanı izni değişiklikleri dahildir.

Yüksek güvenlik modu

StrictMode kullanmak, uygulamanızı geliştirirken ana iş parçacığında yanlışlıkla yapılan G/Ç işlemlerini bulmanıza yardımcı olur. StrictMode'i uygulama veya etkinlik düzeyinde kullanabilirsiniz.

Arka plan ANR iletişim kutularını etkinleştir

Android, yayın mesajını işlemesi çok uzun süren uygulamalar için ANR iletişim kutularını yalnızca cihazın Geliştirici seçeneklerinde Tüm ANR'leri göster etkinleştirilmişse gösterir. Bu nedenle, arka plan ANR iletişim kutuları kullanıcıya her zaman gösterilmese de uygulamada hâlâ performans sorunları yaşanıyor olabilir.

İzleme Görünümü

Kullanım alanlarını incelerken çalışan uygulamanızın izini almak ve ana iş parçacığının meşgul olduğu yerleri tanımlamak için Traceview'u kullanabilirsiniz. Traceview'un nasıl kullanılacağı hakkında bilgi için Traceview ve dmtracedump ile profil oluşturma bölümüne bakın.

İzleme dosyasını alma

Android, ANR yaşadığında iz bilgilerini depolar. Daha eski işletim sistemi sürümlerinde cihazda tek bir /data/anr/traces.txt dosyası bulunur. Daha yeni OS sürümlerinde birden fazla /data/anr/anr_* dosyası vardır. Android Debug Bridge (adb) uygulamasını kök olarak kullanarak bir cihazdan veya emülatörden ANR izlerine erişebilirsiniz:

adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>

Fiziksel bir cihazdan hata raporu almak için cihazdaki Hata raporu geliştiriciyi al seçeneğini veya geliştirme makinenizdeki adb hata raporu komutunu kullanabilirsiniz. Daha fazla bilgi için Hata raporlarını yakalama ve okuma konusuna bakın.

Sorunları düzeltme

Sorunu belirledikten sonra, sık karşılaşılan sorunları düzeltmek için bu bölümdeki ipuçlarından yararlanabilirsiniz.

Ana iş parçacığında yavaş kod var

Kodunuzda, uygulamanın ana iş parçacığının 5 saniyeden uzun süre meşgul olduğu yerleri belirleyin. Uygulamanızdaki şüpheli kullanım alanlarını bulun ve ANR'yi yeniden oluşturmaya çalışın.

Örneğin, Şekil 2'de ana iş parçacığının 5 saniyeden uzun süre meşgul olduğu bir Traceview zaman çizelgesi gösterilmektedir.

Şekil 2. Meşgul bir ana iş parçacığını gösteren Traceview zaman
zaman çizelgesi

2. Şekil. Meşgul bir ana iş parçacığını gösteren Traceview zaman çizelgesi

Şekil 2, aşağıdaki kod örneğinde gösterildiği gibi, rahatsız edici kodun çoğunun onClick(View) işleyicide gerçekleştiğini gösterir:

Kotlin

override fun onClick(v: View) {
    // This task runs on the main thread.
    BubbleSort.sort(data)
}

Java

@Override
public void onClick(View view) {
    // This task runs on the main thread.
    BubbleSort.sort(data);
}

Bu durumda, ana iş parçacığında çalışan çalışmayı bir çalışan iş parçacığına taşımanız gerekir. Android Framework, görevi bir çalışan iş parçacığına taşımaya yardımcı olabilecek sınıflar içerir. Daha fazla bilgi için Çalışan iş parçacıkları bölümüne bakın.

Ana iş parçacığında KS

Ana iş parçacığında IO işlemleri yürütmek, ana iş parçacığında yavaş işlemlerin yaygın nedenlerinden biridir ve bu da ANR'lere neden olabilir. Önceki bölümde gösterildiği gibi, tüm KS işlemlerinin bir çalışan iş parçacığına taşınması önerilir.

G/Ç işlemlerine bazı örnek ağ ve depolama işlemleridir. Daha fazla bilgi için Ağ işlemlerini gerçekleştirme ve Veri tasarrufu konularına bakın.

Kilit anlaşmazlığı

Bazı senaryolarda, ANR'ye neden olan çalışma doğrudan uygulamanın ana iş parçacığında yürütülmez. Bir çalışan iş parçacığı, ana iş parçacığının çalışmasını tamamlamak için gerektirdiği bir kaynakta kilit tutarsa ANR gerçekleşebilir.

Örneğin, Şekil 4'te işin çoğunun bir çalışan iş parçacığında gerçekleştirildiği bir Traceview zaman çizelgesi gösterilmektedir.

Şekil 4. Bir çalışan iş parçacığında yürütülen çalışmayı gösteren Traceview zaman çizelgesi

4. Şekil. Bir çalışan iş parçacığında yürütülen çalışmayı gösteren Traceview zaman çizelgesi

Ancak kullanıcılarınız hâlâ ANR sorunu yaşıyorsa Android Device Monitor'da ana iş parçacığının durumuna bakmanız gerekir. Ana iş parçacığı genellikle kullanıcı arayüzünü güncellemeye hazırsa ve genellikle duyarlıysa RUNNABLE durumundadır.

Ancak ana iş parçacığı yürütmeyi devam ettiremezse BLOCKED durumunda olur ve etkinliklere yanıt veremez. Durum, Android Cihaz Monitörü'nde Şekil 5'te gösterildiği gibi Monitor veya Bekle olarak gösterilir.

Şekil 5. İzleme durumundaki
ana iş parçacığı

5.Şekil İzleme durumundaki ana ileti dizisi

Aşağıdaki iz, bir uygulamanın kaynak beklerken engellenen ana iş parçacığını gösterir:

...
AsyncTask #2" prio=5 tid=18 Runnable
  | group="main" sCount=0 dsCount=0 obj=0x12c333a0 self=0x94c87100
  | sysTid=25287 nice=10 cgrp=default sched=0/0 handle=0x94b80920
  | state=R schedstat=( 0 0 0 ) utm=757 stm=0 core=3 HZ=100
  | stack=0x94a7e000-0x94a80000 stackSize=1038KB
  | held mutexes= "mutator lock"(shared held)
  at com.android.developer.anrsample.BubbleSort.sort(BubbleSort.java:8)
  at com.android.developer.anrsample.MainActivity$LockTask.doInBackground(MainActivity.java:147)
  - locked <0x083105ee> (a java.lang.Boolean)
  at com.android.developer.anrsample.MainActivity$LockTask.doInBackground(MainActivity.java:135)
  at android.os.AsyncTask$2.call(AsyncTask.java:305)
  at java.util.concurrent.FutureTask.run(FutureTask.java:237)
  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
  at java.lang.Thread.run(Thread.java:761)
...

İzi incelemek, ana iş parçacığını engelleyen kodu bulmanıza yardımcı olabilir. Aşağıdaki kod, önceki izdeki ana iş parçacığını engelleyen kilidi tutmaktan sorumludur:

Kotlin

override fun onClick(v: View) {
    // The worker thread holds a lock on lockedResource
    LockTask().execute(data)

    synchronized(lockedResource) {
        // The main thread requires lockedResource here
        // but it has to wait until LockTask finishes using it.
    }
}

class LockTask : AsyncTask<Array<Int>, Int, Long>() {
    override fun doInBackground(vararg params: Array<Int>): Long? =
            synchronized(lockedResource) {
                // This is a long-running operation, which makes
                // the lock last for a long time
                BubbleSort.sort(params[0])
            }
}

Java

@Override
public void onClick(View v) {
    // The worker thread holds a lock on lockedResource
   new LockTask().execute(data);

   synchronized (lockedResource) {
       // The main thread requires lockedResource here
       // but it has to wait until LockTask finishes using it.
   }
}

public class LockTask extends AsyncTask<Integer[], Integer, Long> {
   @Override
   protected Long doInBackground(Integer[]... params) {
       synchronized (lockedResource) {
           // This is a long-running operation, which makes
           // the lock last for a long time
           BubbleSort.sort(params[0]);
       }
   }
}

Diğer bir örnek de aşağıdaki kodda gösterildiği gibi, uygulamanın bir çalışan iş parçacığından sonuç bekleyen ana iş parçacığıdır. Eşzamanlılığı yönetmek için kendi mekanizmaları olan Kotlin'de wait() ve notify() kullanımının önerilen bir kalıp olmadığını unutmayın. Kotlin kullanırken mümkünse Kotlin'e özgü mekanizmalar kullanmalısınız.

Kotlin

fun onClick(v: View) {
    val lock = java.lang.Object()
    val waitTask = WaitTask(lock)
    synchronized(lock) {
        try {
            waitTask.execute(data)
            // Wait for this worker thread’s notification
            lock.wait()
        } catch (e: InterruptedException) {
        }
    }
}

internal class WaitTask(private val lock: java.lang.Object) : AsyncTask<Array<Int>, Int, Long>() {
    override fun doInBackground(vararg params: Array<Int>): Long? {
        synchronized(lock) {
            BubbleSort.sort(params[0])
            // Finished, notify the main thread
            lock.notify()
        }
    }
}

Java

public void onClick(View v) {
   WaitTask waitTask = new WaitTask();
   synchronized (waitTask) {
       try {
           waitTask.execute(data);
           // Wait for this worker thread’s notification
           waitTask.wait();
       } catch (InterruptedException e) {}
   }
}

class WaitTask extends AsyncTask<Integer[], Integer, Long> {
   @Override
   protected Long doInBackground(Integer[]... params) {
       synchronized (this) {
           BubbleSort.sort(params[0]);
           // Finished, notify the main thread
           notify();
       }
   }
}

Lock ve Semaphore kullanan iş parçacıklarının yanı sıra kaynak havuzu (veritabanı bağlantıları havuzu gibi) veya diğer karşılıklı hariç tutma (mutex) mekanizmalarını kullanan iş parçacıkları da dahil olmak üzere ana iş parçacığını engelleyebilecek bazı başka durumlar vardır.

Uygulamanızın kaynaklar üzerinde tuttuğu kilitleri genel olarak değerlendirmeniz gerekir ancak ANR'leri önlemek istiyorsanız ana iş parçacığının gerektirdiği kaynaklar için tutulan kilitlere bakmanız gerekir.

Kilitlerin en kısa süre boyunca tutulduğundan emin olun. Daha da iyisi, uygulamanın askıda tutulması gerekip gerekmediğini değerlendirin. Bir çalışan iş parçacığının işlenmesine dayalı olarak kullanıcı arayüzünün ne zaman güncelleneceğini belirlemek için kilit kullanıyorsanız çalışan iş parçacığı ile ana iş parçacıkları arasında iletişim kurmak için onProgressUpdate() ve onPostExecute() gibi mekanizmalar kullanın.

Kilitlenmeler

Gerekli bir kaynak, aynı zamanda ilk iş parçacığı tarafından barındırılan bir kaynağı bekleyen başka bir iş parçacığı tarafından tutulduğu için bir iş parçacığı bekleme durumuna girdiğinde kilitlenme kilitlenir. Uygulamanın ana iş parçacığı bu durumdaysa ANR'ler gerçekleşme olasılığı yüksektir.

Kilitlenmeler, bilgisayar biliminde uzun süredir iyi çalışılan bir olaydır ve kilitlenmelerden kaçınmak için kullanabileceğiniz kilitlenme önleme algoritmaları vardır.

Daha fazla bilgi için Wikipedia'daki Kilitlenme ve Kilitlenme önleme algoritmaları bölümlerine bakın.

Yavaş yayın alıcıları

Uygulamalar, yayın alıcıları aracılığıyla uçak modunu etkinleştirme veya devre dışı bırakma ya da bağlantı durumunda değişiklik gibi yayın mesajlarına yanıt verebilir. Bir uygulamanın yayın mesajını işlemesi çok uzun sürdüğünde ANR meydana gelir.

ANR aşağıdaki durumlarda gerçekleşir:

  • Yayın alıcısı, onReceive() yöntemini uzun bir süre içinde yürütmeyi tamamlamamıştır.
  • Bir yayın alıcısı goAsync() yöntemini çağırır ve PendingResult nesnesinde finish() çağrısında bulunamaz.

Uygulamanız, BroadcastReceiver onReceive() yönteminde yalnızca kısa işlemler gerçekleştirmelidir. Ancak, uygulamanız bir yayın mesajı nedeniyle daha karmaşık işleme gerektiriyorsa görevi bir IntentService'a ertelemeniz gerekir.

Yayın alıcınızın, uygulamanın ana iş parçacığında uzun süreli işlemler yürütüp yürütmediğini belirlemek için Traceview gibi araçları kullanabilirsiniz. Örneğin, Şekil 6'da ana iş parçacığında bir mesajı yaklaşık 100 saniye boyunca işleyen bir yayın alıcısının zaman çizelgesi gösterilmektedir.

Şekil 6. Ana iş parçacığındaki &quot;BroadcastReceiver&quot; çalışmasını gösteren Traceview zaman çizelgesi

6.Şekil Ana iş parçacığındaki BroadcastReceiver çalışmasını gösteren traceview zaman çizelgesi

Bu davranış, aşağıdaki örnekte gösterildiği gibi BroadcastReceiver için onReceive() yönteminde uzun süreli işlemler yürütmeden kaynaklanabilir:

Kotlin

override fun onReceive(context: Context, intent: Intent) {
    // This is a long-running operation
    BubbleSort.sort(data)
}

Java

@Override
public void onReceive(Context context, Intent intent) {
    // This is a long-running operation
    BubbleSort.sort(data);
}

Bu gibi durumlarda, uzun süreli işlemin bir IntentService öğesine taşınması önerilir çünkü bu işlem, çalışmasını yürütmek için çalışan iş parçacığı kullanır. Aşağıdaki kod, uzun süreli bir işlemi işlemek için IntentService'in nasıl kullanılacağını gösterir:

Kotlin

override fun onReceive(context: Context, intent: Intent) {
    Intent(context, MyIntentService::class.java).also { intentService ->
        // The task now runs on a worker thread.
        context.startService(intentService)
    }
}

class MyIntentService : IntentService("MyIntentService") {
    override fun onHandleIntent(intent: Intent?) {
        BubbleSort.sort(data)
    }
}

Java

@Override
public void onReceive(Context context, Intent intent) {
    // The task now runs on a worker thread.
    Intent intentService = new Intent(context, MyIntentService.class);
    context.startService(intentService);
}

public class MyIntentService extends IntentService {
   @Override
   protected void onHandleIntent(@Nullable Intent intent) {
       BubbleSort.sort(data);
   }
}

IntentService kullanılması sonucunda, uzun süreli işlem ana iş parçacığı yerine bir çalışan iş parçacığında yürütülür. Şekil 7'de, Traceview zaman çizelgesinde çalışan iş parçacığına ertelenen çalışma gösterilmektedir.

Şekil 7. Yayın mesajının bir çalışan iş parçacığında
işlendiğini gösteren Traceview zaman çizelgesi

7. Şekil. Yayın mesajının bir çalışan iş parçacığında işlendiğini gösteren Traceview zaman çizelgesi

Yayın alıcınız, mesajı işlemesinin daha fazla zamana ihtiyacı olduğunu sisteme bildirmek için goAsync() aracını kullanabilir. Ancak PendingResult nesnesinde finish() çağrısı yapmanız gerekir. Aşağıdaki örnekte, sistemin yayın alıcısını geri dönüştürmesini sağlamak ve ANR'yi önlemek için final() çağrısının nasıl yapılacağı gösterilmektedir:

Kotlin

val pendingResult = goAsync()

object : AsyncTask<Array<Int>, Int, Long>() {
    override fun doInBackground(vararg params: Array<Int>): Long? {
        // This is a long-running operation
        BubbleSort.sort(params[0])
        pendingResult.finish()
        return 0L
    }
}.execute(data)

Java

final PendingResult pendingResult = goAsync();
new AsyncTask<Integer[], Integer, Long>() {
   @Override
   protected Long doInBackground(Integer[]... params) {
       // This is a long-running operation
       BubbleSort.sort(params[0]);
       pendingResult.finish();
   }
}.execute(data);

Ancak yayın arka plandayken kodun yavaş bir yayın alıcısından başka bir iş parçacığına taşınması ve goAsync() kullanılması ANR'yi düzeltmez. ANR zaman aşımı hâlâ geçerlidir.

Oyun Etkinliği

GameActivity kitaplığı, C veya C++'ta yazılmış oyun ve uygulamalarla ilgili örnek olaylarda ANR'leri azaltmıştır. Mevcut yerel etkinliğinizi GameActivity ile değiştirirseniz kullanıcı arayüzü iş parçacığı engellemeyi azaltabilir ve bazı ANR'lerin meydana gelmesini engelleyebilirsiniz.

ANR'ler hakkında daha fazla bilgi için Uygulamanızı duyarlı tutma konusuna bakın. İş parçacıkları hakkında daha fazla bilgi için İleti dizisi performansı bölümüne bakın.