Javascript required
Skip to content Skip to sidebar Skip to footer

The Art Students Need to Work on Making a Stop Sign for the Show Using Stacks of Figures

An Android app crashes whenever there'due south an unexpected get out acquired by an unhandled exception or point. An app that is written using Java or Kotlin crashes if it throws an unhandled exception, represented past the Throwable course. An app that is written using native-lawmaking languages crashes if there'southward an unhandled bespeak, such every bit SIGSEGV, during its execution.

When an app crashes, Android terminates the app's process and displays a dialog to allow the user know that the app has stopped, as shown in figure 1.

An app crash on an Android device

Figure 1. An app crash on an Android device

An app doesn't demand to exist running in the foreground for information technology to crash. Whatever app component, even components like broadcast receivers or content providers that are running in the groundwork, can cause an app to crash. These crashes are often disruptive for users because they were not actively engaging with your app.

If your app is experiencing crashes, yous can employ the guidance in this page to diagnose and fix the problem.

Detect the problem

You lot may non always know that your users are experiencing an inordinate number of crashes with your app. If y'all have already published your app, Android vitals can help brand you aware of the problem.

Android vitals

Android vitals can help improve your app's performance past alerting you, via the Play Panel, when your app is exhibiting excessive crashes. Android vitals considers crashes excessive when an app:

  • Exhibits at least i crash in at least ane.09% of its daily sessions.
  • Exhibits 2 or more crashes in at least 0.18% of its daily sessions.

A daily session refers to a 24-hour interval in which your app was used. For information on how Google Play collects Android vitals data, see the Play Console documentation.

After y'all learn that your app is suffering from besides many crashes, the next step is to diagnose them.

Diagnose the crashes

Solving crashes can be difficult. Yet, if you can identify the root crusade of the crash, about probable y'all can find a solution to information technology.

There are many situations that can cause a crash in your app. Some reasons are obvious, similar checking for a nothing value or empty string, merely others are more subtle, like passing invalid arguments to an API or even complex multithreaded interactions.

Crashes on Android produce a stack trace, which is a snapshot of the sequence of nested functions called in your program up to the moment it crashed. Yous can view crash stack traces in Android vitals.

Reading a stack trace

The start step to fix a crash is to identify the identify where it happens. Y'all can use the stack trace bachelor in the report details if you are using Play Console or the output of the logcat tool. If y'all don't have a stack trace available, y'all should locally reproduce the crash, either by manually testing the app or by reaching out to affected users, and reproduce it while using logcat.

The post-obit trace shows an example of a crash on an app written using the Java programming language:

          --------- showtime of crash AndroidRuntime: FATAL EXCEPTION: main Process: com.android.developer.crashsample, PID: 3686 java.lang.NullPointerException: crash sample at com.android.developer.crashsample.MainActivity$ane.onClick(MainActivity.java:27) at android.view.View.performClick(View.java:6134) at android.view.View$PerformClick.run(View.coffee:23965) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.bone.Looper.loop(Looper.java:156) at android.app.ActivityThread.principal(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 organization                  

A stack trace shows two pieces of information that are critical to debugging a crash:

  • The type of exception thrown.
  • The department of lawmaking where the exception is thrown.

The type of exception thrown is usually a very stiff hint as to what went wrong. Look at whether information technology is an IOException, an OutOfMemoryError, or something else, and detect the documentation almost the exception class.

The class, method, file, and line number of the source file where the exception is thrown is shown on the 2nd line of a stack trace. For each role that was chosen, another line shows the preceding call site (called a stack frame). By walking upward the stack and examining the lawmaking, you may discover a identify that is passing an incorrect value. If your code doesn't appear in the stack trace, information technology is likely that somewhere, you passed an invalid parameter into an asynchronous operation. You can oftentimes figure out what happened by examining each line of the stack trace, finding any API classes that you lot used, and confirming that the parameters you passed were correct, and that y'all called it from a place that is allowed.

Stack traces for apps with C and C++ code work much the same way.

          *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Build fingerprint: 'google/foo/bar:10/123.456/78910:user/release-keys' ABI: 'arm64' Timestamp: 2020-02-16 xi:16:31+0100 pid: 8288, tid: 8288, name: com.example.testapp  >>> com.example.testapp <<< uid: 1010332 signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), error 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  /information/app/com.instance.testapp/lib/arm64/libexample.so (com::example::Crasher::crash() const)   #01  pc 0000000000000640  /data/app/com.case.testapp/lib/arm64/libexample.so (com::case::runCrashThread())   #02  pc 0000000000065a3b  /system/lib/libc.so (__pthread_start(void*))   #03  pc 000000000001e4fd  /system/lib/libc.so (__start_thread)                  

If you don't see class and role-level data in native stack traces, you may need to generate a native debug symbols file and upload it to the Google Play Console. For more information, see Deobfuscate crash stack traces. For general information on native crashes, run into Diagnosing native crashes.

Tips for reproducing a crash

It's possible that you can't quite reproduce the problem just by starting an emulator or connecting your device to your computer. Development environments tend to accept more resources, such as bandwidth, retentivity, and storage. Use the type of exception to determine what could be the resource that is deficient, or find a correlation betwixt the version of Android, device type or your app's version.

Retentivity errors

If you take an OutOfMemoryError, so you could create an emulator with low memory capacity to test with. Figure 2 shows the AVD manager settings where y'all tin command the amount of retention on the device.

Memory setting on AVD manager

Figure 2. Memory setting on AVD director

Networking exceptions

Since users oft move in and out of mobile or WiFi network coverage, in an application network exceptions unremarkably should not be treated every bit errors, but rather as normal operating weather condition that happen unexpectedly.

If you need to reproduce a network exception, such as an UnknownHostException, then try turning on airplane fashion while your application attempts to use the network.

Another option is to reduce the quality of the network in the emulator by choosing a network speed emulation and/or a network delay. Y'all can use the Speed and Latency settings on AVD manager, or you can start the emulator with the -netdelay and -netspeed flags, as shown in the following command-line example:

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

This example sets a delay of 20 seconds on all network requests and an upload and download speed of xiv.4 Kbps. For more than information on command-line options for the emulator, see Start the emulator from the command line.

Reading with logcat

Once y'all are able have the steps to reproduce the crash, y'all can use a tool like logcat to get more information.

The logcat output will show you what other log messages yous take printed, along with others from the arrangement. Don't forget to turn off whatsoever extra Log statements that you take added considering printing them wastes CPU and bombardment while your app is running.

Prevent crashes caused by null arrow exceptions

Nil pointer exceptions (identified past the runtime error blazon NullPointerException) occur when you're trying to access an object that is zilch, typically past invoking its methods or accessing its members. Null pointer exceptions are the largest crusade of app crashes on Google Play. The purpose of cipher is to signify that the object is missing - for case, information technology hasn't been created or assigned even so. To avoid null arrow exceptions, you demand to make sure that the object references yous're working with are non-nix before calling methods on them or trying to access their members. If the object reference is null, handle this instance well (for example, exit from a method earlier performing whatever operations on the object reference and write information to a debug log).

Because you don't want to take null checks for every parameter of every method called, you tin rely on the IDE or on the type of the object to signify nullability.

Java programming language

The following sections apply to the Java programming language.

Compile fourth dimension warnings

Comment your methods' parameters and return values with @Nullable and @NonNull to receive compile time warnings from the IDE. These warnings prompt yous to expect a nullable object:

Null pointer exception warning

These nothing checks are for objects that you lot know could be cipher. An exception on a @NonNull object is an indication of an error in your code that needs to be addressed.

Compile time errors

Because nullability should be meaningful, you can embed it in the types you utilise then that there is a compile fourth dimension check for nada. If yous know an object tin can be zippo and that nullability should be handled, you lot could wrap it in an object like Optional. You should e'er prefer types that convey nullability.

Kotlin

In Kotlin, nullability is role of the type system. For example, a variable needs to exist declared from the beginning as nullable or not-nullable. Nullable types are marked with a ?:

          // non-null var s: String = "Howdy"  // null var s: Cord? = "Hello"                  

Non-nullable variables cannot be assigned a goose egg value and nullable variables demand to be checked for nullability before being used as non-aught.

If you don't desire to check for null explicitly, you can utilize the ?. safe call operator:

          val length: Int? = string?.length  // length is a nullable int                                    // if cord is null, and so length is zip                  

Every bit a all-time practise, make sure you accost the null example for a nullable object, or your app could get into unexpected states. If your application won't crash anymore with NullPointerException, you won't know that these errors exist.

The post-obit are some ways to bank check for cipher:

  • if checks

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

    Due to smart-cast and the null check, the Kotlin compiler knows that the cord value is non-null so it allows you to utilize the reference directly, without the need for the safe call operator.

  • ?: Elvis operator

    This operator allows yous to land "if the object is non-null, return the object; otherwise, return something else".

                  val length = string?.length ?: 0                          

You can withal go a NullPointerException in Kotlin. The following are the nigh common situations:

  • When you're explicitly throwing a NullPointerException.
  • When you're using the null assertion !! operator. This operator converts any value to a non-zippo type, throwing NullPointerException if the value is nada.
  • When accessing a cypher reference of a platform type.

Platform types

Platform types are object declarations coming from Java. These types are particularly-treated; goose egg checks are not as enforced, so the non-cypher guarantee is the same every bit in Java. When y'all access a platform type reference, Kotlin does not create compile time errors only these references tin can lead to runtime errors. Run into the following example from the Kotlin documentation:

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

Kotlin relies on blazon inference when a platform value is assigned to a Kotlin variable, or y'all tin can define what type to expect. The best way to ensure the correct nullability country of a reference coming from Java is to use nullability annotations (for case, @Nullable) in your Java code. The Kotlin compiler will represent these references as actual nullable or non-nullable types, not as platform types.

Java Jetpack APIs have been annotated with @Nullable or @NonNull as needed, and a similar approach has been taken in the Android 11 SDK. Types coming from this SDK, that are used in Kotlin, will exist represented as correct nullable or non-nullable types.

Considering of Kotlin's type system, nosotros've seen apps take a major reduction in NullPointerException crashes. For example, the Google Home app saw a 30% reduction in crashes caused by naught arrow exceptions during the year that it migrated new feature evolution to Kotlin.

jobsonbruse1954.blogspot.com

Source: https://developer.android.com/topic/performance/vitals/crash