Kilitlenmeler

Bir Android uygulaması beklenmedik bir çıkış olduğunda bilinmeyen bir istisnaya veya sinyale işaret eder. Java veya Kotlin kullanılarak yazılmış bir uygulama işlenmemiş bir istisnaya neden olursa çökebilir. Throwable sınıfı. durumunda veya C++ kilitlenme sorunu yaşandığında sinyali (örneğin, SIGSEGV) yürütülürken.

Bir uygulama kilitlendiğinde Android, uygulamanın işlemini sonlandırır ve bir iletişim kutusu gösterir. uygulamanın durduğunu kullanıcıya bildirmek için (Şekil 1'de gösterildiği gibi) kullanın.

Android cihazda uygulama kilitlenmesi

Şekil 1. Android cihazda uygulama kilitlenmesi

Bir uygulamanın kilitlenmesi için ön planda çalışıyor olması gerekmez. Tüm uygulamalar bileşen sağlayan ve otomatik olarak devreye giren yayın alıcıları veya arka planda çalıştığı için bir uygulamanın kilitlenmesine neden olabilir. Bu kilitlenmeler kullanıcılar uygulamanızla aktif olarak etkileşime geçmediğinden genellikle kafa karıştırıcıdır.

Uygulamanız kilitlenmelerle karşılaşıyorsa bu sayfadaki yönergeleri kullanarak ve çözüm bulmak sizin işinizdir.

Sorunu tespit etme

Kullanıcılarınızın uygulamanızı kullanırken kilitlenme sorunu yaşadığını her zaman nasıl kullandıklarını da görebiliriz. Uygulamanızı daha önce yayınladıysanız Uygulamanızın kilitlenme oranlarını görmek için Android vitals'ı kullanın.

Android vitals

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

  • Kilitlenme oranı: Günlük etkin kullanıcılarınız arasında herhangi bir kilitlenme yaşamış olabilirsiniz.
  • Kullanıcı tarafından algılanan kilitlenme oranı: Günlük etkin kullanıcılarınızın yüzdesidir. Uygulamanızı etkin şekilde kullanırken en az bir kilitlenme yaşayan (kullanıcı tarafından algılanan kilitlenme). Bir uygulamanın etkin olarak kullanıldığı kabul edilir herhangi bir etkinlik sergiliyorsa veya yürütülüyorsa ön plan hizmeti sunar.

  • Birden fazla kilitlenme oranı: Günlük etkin kullanıcılarınız arasında en az iki kilitlenme yaşandı.

Günlük etkin kullanıcı, uygulamanızı kullanan tekil bir kullanıcıdır (potansiyel olarak birden fazla oturumda) 44 saat boyunca kullanılabilir. Bir kullanıcı aynı gün içinde uygulamanızı birden fazla cihazda kullanırsa her cihaz o gündeki etkin kullanıcı sayısına katkıda bulunur. Birden fazla kullanıcı tek bir gün içinde aynı cihazı kullanırsa bunlar tek bir etkin kullanıcı olarak sayılır.

Kullanıcı tarafından algılanan kilitlenme oranı önemlidir. Diğer bir deyişle, uygulamanızın Google Play'deki bulunabilirliği. Bu önemlidir, çünkü web sitenizin Sayılar her zaman kullanıcı uygulamayla etkileşime geçtiğinde ortaya çıkar. Bu da en çok olabilir.

Play bu metrikte iki kötü davranış eşiği tanımlamıştır:

  • Genel kötü davranış eşiği: Günlük etkin kullanıcıların en az% 1,09'u tüm cihaz modellerinde kullanıcı tarafından algılanan kilitlenme yaşayabilir.
  • Cihaz başına kötü davranış eşiği: Günlük etkin kullanıcıların en az% 8'i tek bir cihaz modelinde kullanıcı tarafından algılanan kilitlenme yaşanması.

Uygulamanız genel kötü davranış eşiğini aşıyorsa büyük olasılıkla tüm cihazlarda daha az bulunabilir. Uygulamanız cihaz başına kötü davranışı aşıyorsa bazı cihazlarda daha az keşfedilebilir, bu nedenle Ayrıca mağaza girişinizde bir uyarı gösterilebilir.

Android vitals sizi Play Console uygulamanız çok fazla kilitlenme gösterdiğinde.

Google Play'in Android vitals verilerini nasıl topladığı hakkında bilgi için bkz. Play Console belgelerinden faydalanabilirsiniz.

Kilitlenmeleri teşhis edin

Uygulamanızın kilitlenmeleri bildirdiğini belirledikten sonra bir sonraki adım bunları teşhis etmektir. Kilitlenmeleri çözmek zor olabilir. Bununla birlikte, küçük bir artışın temel nedenini büyük olasılıkla buna bir çözüm bulabilirsiniz.

Uygulamanızın kilitlenmesine neden olabilecek birçok durum vardır. Bazı nedenler şunlardır: boş bir dize olup olmadığını kontrol etmek gibi açıktır ancak diğerleri bir API'ye geçersiz argümanlar veya karmaşık çok iş parçacıklı etkileşimleridir.

Android'deki kilitlenmeler bir yığın izleme (stack trace) oluşturur. Bu, kilitlendiği ana kadar programınızda çağrılan iç içe yerleştirilmiş işlevler. Şunları yapabilirsiniz: kilitlenmeyle sonuçlanan yığın izlemeleri şurada görüntüle: Android vitals.

Yığın izleme (stack trace) nasıl okunur?

Bir kilitlenmeyi gidermenin ilk adımı, kilitlenmenin meydana geldiği yeri tanımlamaktır. Şunları yapabilirsiniz: Play'i kullanıyorsanız rapor ayrıntılarındaki yığın izlemeden yararlanın Konsol veya logcat aracının çıkışı. Şu durumda: yığın izleme yoksa, kilitlenmeyi yerel olarak yeniden oluşturmanız gerekir, Uygulamayı manuel olarak test ederek veya etkilenen kullanıcılara ulaşarak ve yeniden oluşturmanız gerekir.

Aşağıdaki izde, Java kullanılarak yazılmış bir uygulamadaki kilitlenme örneği gösterilmektedir programlama dili:

--------- beginning of crash
AndroidRuntime: FATAL EXCEPTION: main
Process: com.android.developer.crashsample, PID: 3686
java.lang.NullPointerException: crash sample
at com.android.developer.crashsample.MainActivity$1.onClick(MainActivity.java:27)
at android.view.View.performClick(View.java:6134)
at android.view.View$PerformClick.run(View.java:23965)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6440)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:746)
--------- beginning of system

Yığın izleme, bir yığın izlemede hata ayıklamak için kritik öneme sahip kilitlenme:

  • Atılan istisna türü.
  • Kodda istisnanın atıldığı bölüm.

Atılan istisna türü, genellikle etkinliğin yanlış. Hem sizin hem de tasarımcının IOException ve OutOfMemoryError, özel durum sınıfıyla ilgili dokümanları bulabilirsiniz.

İstisnanın söz konusu olduğu kaynak dosyanın sınıfı, yöntemi, dosyası ve satır numarası değeri, yığın izlemenin ikinci satırında gösterilir. Bu özellik için çağrıldığında, başka bir satır bir önceki çağrı sitesini (yoğun çerçevesi olarak adlandırılır) gösterir. Yığını yükseltip kodu inceleyerek size en uygun yanlış bir değer iletebilir. Kodunuz yığın izlemede görünmüyorsa muhtemelen bir yerde, geçersiz bir parametreyi eşzamansız bir işlemidir. Sorunun ne olduğunu bulmak için genellikle senaryodaki yığın izlemeyi, kullandığınız API sınıflarını bulma ve parametrenin doğru olduğunu ve parametreyi izin verilir.

C ve C++ kodu içeren uygulamaların yığın izlemeleri hemen hemen aynı şekilde çalışır.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/foo/bar:10/123.456/78910:user/release-keys'
ABI: 'arm64'
Timestamp: 2020-02-16 11:16:31+0100
pid: 8288, tid: 8288, name: com.example.testapp  >>> com.example.testapp <<<
uid: 1010332
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
Cause: null pointer dereference
    x0  0000007da81396c0  x1  0000007fc91522d4  x2  0000000000000001  x3  000000000000206e
    x4  0000007da8087000  x5  0000007fc9152310  x6  0000007d209c6c68  x7  0000007da8087000
    x8  0000000000000000  x9  0000007cba01b660  x10 0000000000430000  x11 0000007d80000000
    x12 0000000000000060  x13 0000000023fafc10  x14 0000000000000006  x15 ffffffffffffffff
    x16 0000007cba01b618  x17 0000007da44c88c0  x18 0000007da943c000  x19 0000007da8087000
    x20 0000000000000000  x21 0000007da8087000  x22 0000007fc9152540  x23 0000007d17982d6b
    x24 0000000000000004  x25 0000007da823c020  x26 0000007da80870b0  x27 0000000000000001
    x28 0000007fc91522d0  x29 0000007fc91522a0
    sp  0000007fc9152290  lr  0000007d22d4e354  pc  0000007cba01b640

backtrace:
  #00  pc 0000000000042f89  /data/app/com.example.testapp/lib/arm64/libexample.so (com::example::Crasher::crash() const)
  #01  pc 0000000000000640  /data/app/com.example.testapp/lib/arm64/libexample.so (com::example::runCrashThread())
  #02  pc 0000000000065a3b  /system/lib/libc.so (__pthread_start(void*))
  #03  pc 000000000001e4fd  /system/lib/libc.so (__start_thread)

Yerel yığın izlemelerde sınıf ve işlev düzeyindeki bilgileri görmüyorsanız aşağıdakileri yapmanız gerekebilir: yerel hata ayıklama simgeleri dosyası oluşturma Google Play Console'a yükleyebilirsiniz. Daha fazla bilgi için bkz. Kilitlenmeyle sonuçlanan yığın izlemelerin (stack trace) kodunu gösterme. Yerel kilitlenmeler hakkında genel bilgi için şuraya bakın: Yerel kilitlenmeleri teşhis etme.

Kilitlenmeleri yeniden oluşturmaya ilişkin ipuçları

Belki de ilk birkaç adımı uygulayarak sorunu yeniden bir emülatör kullanmak ya da cihazınızı bilgisayarınıza bağlamaktır. Geliştirme ortamları bant genişliği, bellek ve depolama alanı gibi daha fazla kaynağa sahip olabilir. Şunu kullanın: kıt olan kaynağın ne olabileceğini belirlemek için bir istisna türü veya Android sürümü, cihaz türü veya uygulamanızın sürümünü değil.

Bellek hataları

Bir OutOfMemoryError test etmek için düşük bellek kapasitesine sahip bir emülatör oluşturabilirsiniz. Figür 2'de, cihazınızda bulunan bellek miktarını kontrol edebileceğiniz ortalama görüntüleme süresi yöneticisi ayarları gösteriliyor. için geçerlidir.

AVD yöneticisindeki bellek ayarı

Şekil 2. AVD yöneticisindeki bellek ayarı

Ağ iletişimi istisnaları

Kullanıcılar sık sık mobil veya kablosuz ağ kapsamına dahil olup kapsam dışına çıktıkları için, uygulama ağı istisnaları genellikle hata olarak değerlendirilmemelidir, ancak beklenmedik şekilde gerçekleşen normal çalışma koşulları gibidir.

Bir ağ istisnası (ör. UnknownHostException ardından uygulamanız ağ.

Diğer bir seçenek de emülatördeki ağın kalitesini bir ağ hızı emülasyonu ve/veya ağ gecikmesi seçme. URL parametrelerinin Google tarafından nasıl ele alınmasını istediğinizi belirtmek için AVD yöneticisindeki Hız ve Gecikme ayarlarını ya da emülatörü başlatabilirsiniz. aşağıda gösterildiği gibi, -netdelay ve -netspeed işaretleriyle komut satırı örneği:

emulator -avd [your-avd-image] -netdelay 20000 -netspeed gsm

Bu örnekte, tüm ağ isteklerinde 20 saniyelik bir gecikme ve bir yüklemede ve 14,4 Kb/sn indirme hızına sahiptir. Komut satırı seçenekleri hakkında daha fazla bilgi için için bkz. Emülatörü komut satırından başlatın.

Logcat ile okuma

Kilitlenmeyi yeniden oluşturmak için gerekli adımları elde ettikten sonra, Daha fazla bilgi edinmek için logcat.

Logcat çıkışı, yanında yazdırdığınız günlük mesajlarını gösterir. iletişim kurabilmenizi sağlar. Ekstraları kapatmayı unutmayın Log Çünkü uygulamanız çalışırken CPU ve pili harcar çalışıyor.

Boş işaretçi istisnalarından kaynaklanan kilitlenmeleri önle

Boş işaretçi istisnaları (çalışma zamanı hatası türüyle tanımlanır) NullPointerException), null (genellikle yöntemlerini çağırarak veya üyelerine erişir). Null işaretçi istisnaları Google Play'de uygulama kilitlenmelerinin en büyük nedenlerindendir. Amacı null, nesnenin eksik olduğunu (örneğin, oluşturulmuş veya henüz atanmamıştır. Boş işaretçi istisnalarını önlemek için çağrı yapmadan önce çalıştığınız nesne başvurularının boş olmadığından emin olun. veya üyelerine erişmeye çalışan kişiler olabilir. Nesne referansı null, bu durumu iyi ele alın (örneğin, gerçekleştirmeden önce bir yöntemden çıkın nesne referansı üzerinde işlem yapabilir ve hata ayıklama günlüğüne bilgi yazabilirsiniz).

Her yöntemin her parametresi için boş kontrollerin olmasını istemediğinizden geliştirmek için IDE'ye veya bu nesneyi belirtmek için nesnenin türüne null bulunabilirlik.

Java programlama dili

Aşağıdaki bölümler Java programlama dili için geçerlidir.

Derleme zamanı uyarıları

Yöntemlerinize not ekleyin ve parametrelerin değerini döndürür @Nullable ve Derleme zamanını almak için @NonNull uyarı olarak devreye girer. Aşağıdaki uyarılar, boş değer içeren bir nesne beklemenizi ister:

Boş işaretçi istisna uyarısı

Bu null kontroller, null olabileceğini bildiğiniz nesneler içindir. Bir sorun nedeniyle @NonNull nesnesi, kodunuzda düzeltilmesi gereken bir hata olduğunu gösterir ele alınır.

Derleme zamanı hataları

Boş değer atanabilirliği anlamlı olması gerektiğinden, kullandığınız türlere yerleştirebilirsiniz Böylece null için bir derleme zamanı kontrolü elde edersiniz. Bir nesnenin null ve bu null değeri işlenmelidir. Bunu şunun gibi bir nesne içine sarabilirsiniz: Optional. Her zaman, boş değer içeren türleri tercih etmeniz gerekir.

Kotlin

Kotlin'de boş değer tür sisteminin bir parçasıdır. Örneğin, bir değişkenin başına boş değer atanabilir veya null olamaz. Boş değer atanabilen türler ? ile işaretlenir:

// non-null
var s: String = "Hello"

// null
var s: String? = "Hello"

Null yapılamayan değişkenlere null değer ve boş değer atanamayan değişkenler atanamaz null olmayan bir değer olarak kullanılmadan önce null olup olmadığının kontrol edilmesi gerekir.

Null'u açıkça kontrol etmek istemiyorsanız ?. güvenli çağrısını kullanabilirsiniz operatör:

val length: Int? = string?.length  // length is a nullable int
                                   // if string is null, then length is null

En iyi uygulama olarak, boş değerli bir nesne için boş büyük/küçük harf düzenini ele aldığınızdan emin olun. Aksi takdirde uygulamanız beklenmeyen durumlara düşebilir. Uygulamanız kilitlenmiyorsa artık NullPointerException ile bu hataların varlığından haberdar olmazsınız.

Aşağıda, null değerini kontrol etmenin bazı yolları verilmiştir:

  • if kontrol

    val length = if(string != null) string.length else 0
    

    Akıllı yayın ve boş kontrolü sayesinde, Kotlin derleyicisi dize değeri null olmadığından, referansı doğrudan kullanmanıza olanak tanır. Bu sayede güvenli arama operatörüne ihtiyaç duymazsınız.

  • ?: Elvis operatörü

    Bu operatör, "nesne boş olmayan bir değerse nesne; Aksi takdirde başka bir şey döndürün".

    val length = string?.length ?: 0
    

Kotlin'de yine de NullPointerException alabilirsiniz. Aşağıda en sık karşılaşılan yaygın durumlar:

  • Açıkça NullPointerException attığınızda.
  • nullapproval !! operatörü. Bu operatör, tüm değerleri boş olmayan bir türe dönüştürür. Değer null ise NullPointerException.
  • Bir platform türünün boş referansına erişirken.

Platform türleri

Platform türleri, Java'dan gelen nesne bildirimleridir. Bu türler özel olarak işlenir; null kontrolleri zorunlu kılınmadığı için null olmayan garanti aşağıdakiyle aynıdır: Java. Platform türü referansına eriştiğinizde Kotlin derleme oluşturmaz zaman hataları var, ancak bu referanslar çalışma zamanı hatalarına neden olabilir. Aşağıdakilere göz atın bir örnek görebilirsiniz:

val list = ArrayList<String>() // non-null (constructor result) list.add("Item")
val size = list.size // non-null (primitive int) val item = list[0] // platform
type inferred (ordinary Java object) item.substring(1) // allowed, may throw an
                                                       // exception if item == null

Kotlin'e bir platform değeri atandığında Kotlin, tür çıkarımına dayanır değişkeni belirleyebilir veya ne tür bir değer bekleneceğini tanımlayabilirsiniz. Web sitenizin URL'sini Java'dan gelen bir referansın doğru nulllanabilirlik durumu, boş değer kullanmaktır ek açıklamaları (örneğin, @Nullable) ekleyin. Kotlin derleyici bu referanslar, aşağıdaki gibi değil, gerçek null veya null yapılamayan türler olarak temsil edilir platform türleri.

Java Jetpack API'lerine gerektiği gibi @Nullable veya @NonNull ek açıklamaları eklendi, Ayrıca Arkadaş Bitkiler projesinde de Android 11 SDK'sı Bu SDK'dan gelip Kotlin'de kullanılan türler şu şekilde gösterilir: Doğru değer atanabilir veya boş değer atanamayan türler olmalıdır.

Kotlin'in tür sistemi sayesinde uygulamaların, görüntüleme hacminde büyük bir azalmaya NullPointerException kilitlenme. Örneğin Google Home uygulaması, yıl boyunca boş işaretçi istisnalarından kaynaklanan kilitlenmelerdeki düşüş yeni özellik geliştirmesini Kotlin'e taşıdı.