Summary of Android Practical Development bug s

Introduction to Catalogue

  • 1.1 java.lang.UnsatisfiedLinkError could not find so Library Exception
  • 1.2 java.lang.IllegalStateException illegal state exception
  • 1.3 android.content.res.Resources$NotFoundException
  • 1.4 java.lang.IllegalArgumentException parameter mismatch exception
  • 1.5 IllegalStateException: Can't compress a recycled bitmap
  • 1.6 java.lang.NullPointerException null pointer exception
  • 1.7 android. view. Windows Manager $BadTokenException exception
  • 1.8 java.lang.ClassCastException class transformation exception
  • 1.9 Toast runs on sub-threading issues, handler issues
  • 2.1 The java.lang.ClassNotFoundException class could not find an exception
  • 2.2 java.util.concurrent.TimeoutException connection timeout crash
  • 2.3 java.lang.NumberFormatException format conversion error
  • 2.4 java.lang.IllegalStateException: Fragment not attached to Activity
  • 2.5 Array IndexOutOfBoundsException Corner Crossing Anomaly
  • 2.6 Constructing method permission exception in IllegalAccessException method
  • 2.7 android. view. Windows Manager $BadTokenException, dialog window exception
  • 2.8 java.lang.NoClassDefFoundError could not find class exception
  • 2.9 Android appears: Your project path contains non-ASCII characters.
  • 3.1 OnErrorNotImplementedException[ Can't create handler inside thread that has not called Looper.prepare()]
  • 3.2 adb.exe,start-server' failed -- run manually if necessary
  • 3.3 java.lang.IllegalStateException: ExpectedBEGIN_OBJECT but was STRING at line 1 column 1 path $
  • 3.4 android.content.ActivityNotFoundException: No Activity found to handle Intent
  • 3.5 Package manager has died leading to crash
  • 3.6 Illegal ArgumentException View Add Window Error
  • 3.7 Illegal State Exception: Not allowed to start service Intent exception crash
  • 3.8 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
  • 3.9 In Fragment, the context is not found through getActivity, and null causes null pointer exceptions
  • 4.1 Illegal ArgumentException crashes [url address passes in illegal parameters, escape characters]
  • 4.2 ClassNotFoundException: Didn't find class "" on path: /data/app/* error
  • 4.3 NoClassDefFoundError exception [which indicates that the class definition cannot be found]
  • 4.4 The previous project used customer service udesk, and initialization after sdk update caused crash problem.
  • 4.5 java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception
  • 4.6 java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException
  • 4.7 00768556/vendor/lib/libllvm-glnext.so [armeabi-v8] Failure to load so libraries resulted in crash
  • 4.8 Only the original thread that created a view hierarchy can touch its views
  • 4.9 NoSuchMethodException android.support.v4.app.Fragment$InstantiationException

Hot wire

  • Blog Notes Summary [March 16 to date], including Java foundation and in-depth knowledge points, Android technology blog, Python learning notes and so on, including the usual development of the bug summary, of course, also in the spare time to collect a large number of interview questions, long-term updates and maintenance and correction, continuous improvement... Open source files are in markdown format! At the same time, life blog has been open source. Since 12 years ago, it has accumulated a total of 47 articles [nearly 200,000 words]. Please indicate the source for reprinting. Thank you!
  • Link Address: https://github.com/yangchong2...
  • If you feel good, you can start. Thank you. Of course, you are also welcome to make suggestions. Everything starts at a slight moment, and quantitative change causes qualitative change.

1.1 java.lang.UnsatisfiedLinkError

  • A. Detailed crash log information

    # main(1)
    java.lang.UnsatisfiedLinkError
    dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.paidian.hwmc-1/base.apk", dex file "/data/app/com.paidian.hwmc-1/base.apk"],nativeLibraryDirectories=[/data/app/com.paidian.hwmc-1/lib/arm64, /data/app/com.paidian.hwmc-1/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]]] couldn't find "libijkffmpeg.so"
  • B. View crash class information

    • The main idea of this exception class is that if the Java Virtual Machine cannot find the appropriate native language definition for the method declared as native, it raises.
    public class UnsatisfiedLinkError extends LinkageError {
        private static final long serialVersionUID = -4019343241616879428L;
    
        public UnsatisfiedLinkError() {
            super();
        }
    
        public UnsatisfiedLinkError(String s) {
            super(s);
        }
    }
  • C. Anomaly Analysis in Project

    • According to the actual project, when preparing to play video, libijkffmpeg.so library can not be found, resulting in a direct crash.
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • Reporting this error is usually a failure to load the so library, or a JNI method to be executed is not found:

      • 1. It is recommended to check if so is lost in the process of installation and not placed in the specified directory.
      • 2. When calling load library, check whether the correct so file name has been called, capture it and deal with it accordingly to prevent the program from crashing.
      • 3. Check if the so architecture is one to the device architecture (such as calling 32-bit so under 64-bit architecture).
    • Code presentation
    ndk {
        //Select the. so libraries that correspond to the type of cpu to be added as needed.
        //abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'mips'
        abiFilters 'armeabi-v7a'
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        //These two must be added, and the other options are available.
        compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.4'
        compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
        //Other library files
        //compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.8'
        //compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
        //compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.8'
        //compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.8'
    }
  • G. Knowledge extension

    • Android application developers should be familiar with UnsatisfiedLink Error, a type of error that has been plaguing most developers. Have you ever thought about the possibility that you did nothing wrong and that this problem will arise?
    • In the course of Android application development and testing, we have encountered a case in which the apk crashes when it is installed on a certain model, reporting an error of UnsatisfiedLink Error.
    • java.lang.UnsatisfiedLinkError: Couldn't load mobsec from loader dalvik.system.PathClassLoader.....findLibrary returned null
    • First of all, it is suspected that libmobsec.so is not placed in the corresponding libsabi directory in the apk. However, the inspection found that this so has been placed under all libsabi, and continue to investigate.
    • Then the idea is that the so placed is not corresponding to abi. For example, because of careless placement of so in the armeabi directory, the x86 instruction set is loaded on the armeabi instruction set mobile phone, which is also excluded.
    • In the absence of clues, when we think of loading so by the System. Load Library function, the system is loaded from a specified path, so does so exist under this path?
    • We know that the application's private Native library directory / data / data / package name / lib is a symbolic link to the / data / app - lib /< package name > directory, to which System. load Library tries to load so.
    • adb shell to this path, use the command ls to view, as expected, this libmobsec.so does not exist. So what causes it?
    • By analyzing the implementation of Android system source code, it is found that the so in the directory of / data / app-lib /< package name > is extracted from the Lib directory of APK when the system installs apk.

1.2 java.lang.IllegalStateException illegal state exception

  • A. Detailed crash log information

    • The onSaveInstanceState method is called before the Activity is about to be destroyed to save the Activity data, if the play status is saved.

Adding Fragment s to it will make a mistake.

IllegalStateException: Can not perform this action after onSaveInstanceState: 
  • B. View crash class information

    • A signal that calls a method at an illegal or inappropriate time. In other words, the Java environment or Java application is not in the proper state for requesting operations.
    public class IllegalStateException extends RuntimeException {
        public IllegalStateException() {
            super();
        }
    
        public IllegalStateException(String s) {
            super(s);
        }
    
        public IllegalStateException(String message, Throwable cause) {
            super(message, cause);
        }
    
        public IllegalStateException(Throwable cause) {
            super(cause);
        }
    
        static final long serialVersionUID = -1848914673093119416L;
    }
  • C. Anomaly Analysis in Project

    • Analysis
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • The solution is to replace the commit() method with commitAllowingStateLoss()
  • G. Other Extensions

    • The error types are roughly the following:
    java.lang.IllegalStateException: Can't change tag of fragment d{e183845 #0 d{e183845}}: was d{e183845} now d{e183845 #0 d{e183845}}
    java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 37 path $.data
    • First: I used fragment. show (getSupportFragment Manager, fragment. toString()) in the code for displaying fragments; this is because two toString() results are different, resulting in different tags pointing to the same fragment. The correct way to get a fragment tag is to use the fragment.getTag() method it provides.
    • The second is that the exception is caused by the different structure of JSON string returned by server error and JSON string returned by server under normal condition, which causes an exception to be reported when Gson parses: the set should be parsed but the object is forced to be parsed. Solution: try case when Gson parses JSON, do not report errors according to the rule Normal logic continues to parse, exception reporting is handled as request failure logic.

1.3 android.content.res.Resources$NotFoundException

  • A. Detailed crash log information

    • Android resources are not renderable (color or path)
    Resource is not a Drawable (color or path): TypedValue{t=0x2/d=0x7f040151 a=2}
    android.view.LayoutInflater.createView(LayoutInflater.java:620)
  • B. View crash class information

    • When the requested resource is not found, the resource API raises this exception.
    public static class NotFoundException extends RuntimeException {
        public NotFoundException() {
        }
    
        public NotFoundException(String name) {
            super(name);
        }
    
        public NotFoundException(String name, Exception cause) {
            super(name, cause);
        }
    }
  • C. Anomaly Analysis in Project

    • Since the image resources are copied to the drawable-land-xhdpi directory, they should have been copied to the drawable-xhdpi directory.
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • 1. Can the reference resource ID match the resources defined in the R.java file?
    • 2. Whether due to caching or other reasons, APK can be decompiled and checked if the resource files are not packaged in the compiler.
    • 3. Whether an error type is used to refer to a resource or to configure a resource is incorrect;
    • 4. Whether Int and other integer variables are passed as parameters to View.setText call, in this case, the integer variable will be considered as a resource ID number to find the corresponding resources in the list of resources, resulting in the failure to find the corresponding resources; the solution is to do type conversion View.setText(String.valueOf(Int id)).

1.4 java.lang.IllegalArgumentException parameter mismatch exception

  • A. Detailed crash log information
  • B. View crash class information

    • Parametric mismatch exceptions are usually caused by passing incorrect parameters.
    public class IllegalArgumentException extends RuntimeException {
        public IllegalArgumentException() {
            super();
        }
    
        public IllegalArgumentException(String s) {
            super(s);
        }
    
        public IllegalArgumentException(String message, Throwable cause) {
            super(message, cause);
        }
    
    
        public IllegalArgumentException(Throwable cause) {
            super(cause);
        }
    
        private static final long serialVersionUID = -5365630128856068164L;
    }
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs
  • F. Solutions
  • G. Common scenarios

    • Activity, Service status exception;
    • Illegal URL;
    • UI thread operation.
    • Sub Fragments are nested in Fragments, and Fragments are destroyed, while internal Fragments are not destroyed, which leads to duplication when loading again, and internal Fragments can be destroyed in onDestroyView().
    • Glide. in (view) is used in callbacks to the requesting network, and view has been destroyed leading to this error

1.5 IllegalStateException: Can't compress a recycled bitmap

  • A. Detailed crash log information

    • Unable to compress recovery bitmaps
    Can't compress a recycled bitmap
    com.paidian.hwmc.utils.i.a(FileUtils.java:75)
  • B. View crash class information

    • If the bitmap has been reclaimed, the method wishing to throw an exception will call this value. Knowing the specific location of the collapse, we should analyze the specific reasons.
    public boolean compress(CompressFormat format, int quality, OutputStream stream) {
        checkRecycled("Can't compress a recycled bitmap");
        //Eliminate code
        return result;
    }
    
    //If the bitmap has been reclaimed, the method wishing to throw an exception will call this value.
    private void checkRecycled(String errorMessage) {
        if (mRecycled) {
            throw new IllegalStateException(errorMessage);
        }
    }
  • C. Anomaly Analysis in Project

    • Objects that have been freed from memory are used. For Bitmap: Bitmap bitmap = a bitmap object. Call bitmap.recycle() during use, and then use bitmap to report an error.
  • D. Process analysis of triggering crash logs

    • bitmap.recycle() explains as follows, releases the native objects associated with this bitmap and clears references to pixel data. This will not release the pixel data synchronously; it will only allow garbage collection without other references. The bitmap is marked "dead", which means that if getPixels() or setPixels() are called, it will throw an exception without drawing anything. This operation cannot be inverted, so it should only be invoked if it is determined that no further bitmap is used. This is a high-level call, which is usually not required, because when there is no reference to the bitmap, the normal GC process releases this memory.
    Free the native object associated with this bitmap, and clear the reference to the pixel data
  • F. Solutions

    • The first is to add judgement before using bitmap, if (mBitmap.isRecycled()) return null;

1.6 java.lang.NullPointerException null pointer exception

  • A. Detailed crash log information

    Please call the AutoSizeConfig#init() first
    com.paidian.hwmc.base.BaseApplication.initAutoSizeConfig(BaseApplication.java:386)
  • B. View crash class information

    • Null pointer exception is also a very common exception
    public class NullPointerException extends RuntimeException {
        private static final long serialVersionUID = 5162710183389028792L;
        public NullPointerException() {
            super();
        }
        public NullPointerException(String s) {
            super(s);
        }
    }
  • C. Anomaly Analysis in Project

    • Null pointer occurrence scenario is more, refers to an object reported null, this use to use it, i will report the exception.
  • D. Process analysis of triggering crash logs

    • Reasons for null pointers: Two conditions must be met before null pointers occur: the reference variable points to null and the method of the reference is invoked
    • The solution of null pointer problem:

      • Look at the Log information and see the code that causes the null pointer to occur in the first line. Double-click the class that opens the null pointer directly.
      • Look at several calls to methods in this line of code, and several objects may be empty to find out which object is empty
      • See where these people are assigned.
      • If there is no assignment, assign it to her and solve the problem.
      • If there is a place to assign a value, see if the method is called (Ctrl + Shift + G)
      • If there is no call (maybe no call or maybe it's too late), call assignment before using it. Problem solving
      • If there is a call, see if there are other places to give her a value of null, if not set to null, it depends on whether the variable assigned and the variable we use is the same variable.
  • F. Solutions

    • Null pointer is the most common and easy to avoid. When using null check, we must adopt the principle of distrust:

      • 1. The method parameters should be judged blank before they are used.
      • 2. Global variables are easy to be reclaimed or changed by the system. It is recommended to empty them before using global variables.
      • 3. Call of the third-party interface to empty the return value.
      • 4. Please pay attention to thread safety

1.7 android. view. Windows Manager $BadTokenException exception, Toast error Unable to add window

  • A. Detailed crash log information

    android.view.WindowManager$BadTokenException
        Unable to add window -- token android.os.BinderProxy@7f652b2 is not valid; is your activity running?
  • B. View crash class information

    • Where does the query error log come from?
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs

    • This exception occurs when Toast displays because token fails. Normally, such anomalies do not occur. But in some cases, a message from a UI thread of the Android process blocked. The show method that causes TN to post out a 0 (display) message is located after the message and is delayed in execution. At this point, the Notification Manager's timeout detection ends and the token record in the WMS service is deleted. The deletion of token occurs before the Android process show method. This leads to the above anomalies.
    • Test code. It's easy to simulate the occurrence of anomalies. This is the only way to solve the above problem.
     Toast.makeText(this,"Xiaoxiang Sword Rain-yc",Toast.LENGTH_SHORT).show();
        try {
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
  • F. Solutions

    • At present, I have seen several kinds. It's better to think about that kind of thing.
    • First, since it is your activity running, can we judge whether the activity is running before toast?
    • Second, throw an exception and add try-catch. The code is as follows, but it still can't solve the problem.

      • According to source code analysis, the exception occurs in the next UI thread message, so it is meaningless to add try-catch to the last UI thread message. And it's inconvenient to use so many places for toast.
    • The third is to customize a view control similar to Toast. Personal advice is not to do this unless it is very demanding. After all, such anomalies are relatively rare.
  • G. What will happen to this problem?

    • The UI thread performs a very time-consuming operation, such as loading pictures and so on, similar to the sleep simulation above.
    • Processes are back-end or on the screen. In order to reduce power consumption or for some reason, the system allocates less cpu time to the process, which results in that the instructions in the process can not be executed in time. This will also cause the process to look "karton".
    • When TN throws a message, there are a large number of UI thread messages waiting to be executed, and each UI thread message is not jammed, but if the total time exceeds the Notification Manager's timeout, there will still be problems.

1.8 java.lang.ClassCastException class transformation exception

  • A. Detailed crash log information

    android.widget.FrameLayout cannot be cast to android.widget.RelativeLayout
    com.paidian.hwmc.goods.activity.GoodsDetailsActivity.initView(GoodsDetailsActivity.java:712)
  • B. View crash class information

    • Throws to indicate that the code attempts to coerce an object into a subclass that is not an instance.
    public class ClassCastException extends RuntimeException {
        private static final long serialVersionUID = -9223365651070458532L;
    
    
        public ClassCastException() {
            super();
        }
    
        public ClassCastException(String s) {
            super(s);
        }
    }
  • C. Anomaly Analysis in Project

    • This exception represents a type conversion exception, usually because one class object is converted to an exception thrown by another incompatible class object. Check the type of class object you want to convert.
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • Generally occurs when type conversion is mandatory, for example, if A is converted to B and A is not the parent class of B, a java.lang.ClassCastException exception will be generated. Generally, it is recommended to use instanceof to make type judgment and then to make conversion.
    • In this case, you need to change FrameLayout to Relative Layout.

1.9 Toast runs on sub-threading issues, handler issues

  • A. Detailed crash log information

    • Let's look at the problem code first. What problems will arise?
    new Thread(new Runnable() {
        @Override
        public void run() {
            ToastUtils.showRoundRectToast("Xiaoxiang Sword Rain-Yang Cheng");
        }
    }).start();
    • The error log is as follows:
  • Then find out where the error log came from.

    • ![image]()
  • The correct way to do toast in a sub-thread is as follows

    new Thread(new Runnable() {
        @Override
        public void run() {
            Looper.prepare();
            ToastUtils.showRoundRectToast("Xiaoxiang Sword Rain-Yang Cheng");
            Looper.loop();
        }
    }).start();
  • The conclusions reached

    • Toast can also be executed in sub-threads, but you need to provide the Looper environment manually.
    • When Toast calls the show method display, the internal implementation is executed by Handler, so naturally it does not block the Binder thread. In addition, if the addView thread is not a Loop thread, the execution ends, of course, there is no chance to execute subsequent requests, which is guaranteed by Hanlder's constructor. Look at the handler's constructor. If Looper==null, an error will be reported, and when Toast objects are instantiated, they will instantiate a Hanlder for themselves. That's why "must be in the main thread". Actually, it should be "must be in the Looper non-empty thread".
    • The constructor of Handler is as follows:

2.1 The java.lang.ClassNotFoundException class could not find an exception

  • A. Detailed crash log information

    Didn't find class "om.scwang.smartrefresh.layout.SmartRefreshLayout" on path: DexPathList[[zip file "/data/app/com.paidian.hwmc-EsIbVq6e0mFwE0-rPanqdg==/base.apk", zip file "/data/app/com.paidian.hwmc-EsIbVq6e0mFwE0-rPanqdg==/split_lib_dependencies_apk.apk", zip file "/data/app/com.paidian.hwmc-EsIbVq6e0mFwE0-rPanqdg==/split_lib_slice_0_apk.apk", zip file "/data/app/com.paidian.hwmc-EsIbVq6e0mFwE0-rPanqdg==/split_lib_slice_1_apk.apk", zip file "/data/app/com.paidian.hwmc-EsIbVq6e0mFwE0-rPanqdg==/split_lib_s
    com.paidian.hwmc.goods.activity.GoodsDetailsActivity.onCreate(GoodsDetailsActivity.java:209)
  • B. View crash class information

    • Raised when an application attempts to load a class with a string name: but the definition of a class with a specified name cannot be found. Since version 1.4, this exception has been modified to conform to the general exception linking mechanism. The "optional exception raised when loading a class" provided at build time and accessed through the {@link#getException()} method is now called cause, and can be accessed through the {@link Throwable#getCace()} method and the "legacy method" mentioned earlier.
    public class ClassNotFoundException extends ReflectiveOperationException {
        private static final long serialVersionUID = 9176873029745254542L;
        private Throwable ex;
        public ClassNotFoundException() {
            super((Throwable)null);  // Disallow initCause
        }
        public ClassNotFoundException(String s) {
            super(s, null);  //  Disallow initCause
        }
        public ClassNotFoundException(String s, Throwable ex) {
            super(s, null);  //  Disallow initCause
            this.ex = ex;
        }
        public Throwable getException() {
            return ex;
        }
        public Throwable getCause() {
            return ex;
        }
    }
  • C. Anomaly Analysis in Project

    • This exception indicates that the specified class cannot be found under the path, usually due to the problem of constructing the path.
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • Class names are identified in the form of strings and have low credibility. When calling Class. forName ("), Class. findSystemClass ("), Class. loadClass ("), etc., an error will be reported if the class name is not found. If the missing lass is the Class of the system, then it may be the compatibility of the system version and the compatibility of the manufacturer Rom. To find the corresponding device and try to reproduce it, the solution can consider replacing the Api or replacing it with the Class implemented by ourselves.
    • If the missing CLASS is an application free Class (CLASS with a third-party SDK), you can check whether the corresponding apk really lacks the Class by decompiling tools, and then locate it. This often happens:

      • 1. The lass to be looked for was confused, existed but its name changed.
      • 2. The Class that you are looking for has not been entered into Dex. It really does not exist. It may be due to your negligence or the conflict of compiling environment.
      • 3. The lass you're looking for does exist, but your lasslorder can't find the Class, often because it's self-implemented (common in plug-in applications).
  • G. Other Extensions

2.2 java.util.concurrent.TimeoutException connection timeout crash

  • A. Detailed crash log information

    java.util.concurrent.TimeoutException: android.view.ThreadedRenderer.finalize() timed out after 10 seconds
    at android.view.ThreadedRenderer.nDeleteProxy(Native Method)
    at android.view.ThreadedRenderer.finalize(ThreadedRenderer.java:423) 
  • B. View crash class information

    • An exception that is thrown when the blocking operation times out. Specifying a timeout blocking operation requires a way to indicate that a timeout has occurred. For many such operations, you can return a value indicating a timeout; if it is not possible or necessary, you should declare and throw {@code TimeoutException}.
    public class TimeoutException extends Exception {
        private static final long serialVersionUID = 1900926677490660714L;
        public TimeoutException() {}
        public TimeoutException(String message) {
            super(message);
        }
    }
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • Generally, when the system is in gc, the finalize timeout of the calling object results in the solution:
    • 1. Check and analyze why finalize is time-consuming and fix it.
    • 2. Check the log to see if GC is too frequent, causing timeouts, reducing content overhead, and preventing memory leaks.
  • G. Other Extensions

2.3 java.lang.NumberFormatException format conversion error

  • A. Detailed crash log information

    Exception in thread "main" java.lang.NumberFormatException: For input string: "100 "
        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
        at java.lang.Integer.parseInt(Integer.java:458)
        at java.lang.Integer.parseInt(Integer.java:499)
  • B. View crash class information

    • Triggered to indicate that the application is trying to convert a string to one of the digital types, but the string is not properly formatted.
    public class NumberFormatException extends IllegalArgumentException {
        static final long serialVersionUID = -2848938806368998894L;
    
        public NumberFormatException () {
            super();
        }
    
        public NumberFormatException (String s) {
            super (s);
        }
    
        static NumberFormatException forInputString(String s) {
            return new NumberFormatException("For input string: \"" + s + "\"");
        }
    }
  • C. Anomaly Analysis in Project

    • The error keyword java.lang.NumberFormatException clearly tells us that it is a digital format exception, followed by the For input string: "100" prompt, which tells us that there is a mistake in converting "100" into a digital type, so it is very accurate.
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • The solution is simple. Change to Integer.parseInt(str.trim()) and pay attention to the need for trim when converting strings into integer data types.
  • G. Other Extensions

2.4 java.lang.IllegalStateException: Fragment not attached to Activity

  • A. Detailed crash log information

    java.lang.IllegalStateException: Fragment not attached to Activity
  • B. View crash class information
  • C. Anomaly Analysis in Project

    • This exception occurs because Fragment calls functions such as getResource() that require contextual Content before Attach reaches Activity.
    • This exception occurs because when Fragment has not Attach to Activity, it calls functions such as getResource(), which require Context context Context. The solution is to wait until the calling code is written in OnStart().
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • Run the invoked code over the lifetime of Fragment Attached.
    • First: before calling a function that requires Context, add a judgment isAdded()
    if(isAdded()){//The isAdded method is provided by the Android system and returns true only after Fragment is added to the Activeness to which it belongs.
        activity.getResourses().getString(...);
    }
    • The second is as follows
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        activity = (MainActivity) context;
    }
    
    @Override
    public void onDetach() {
        super.onDetach();
        if (activity != null) {
            activity = null;
        }
    }
  • G. Other Extensions

    • Scenario: This error often occurs when a fragment thread performs a time-consuming operation that calls getResources to update the ui after execution. If the thread operation is not completed, call getActivity().recreate() to reload activity or screen rotation, and there will be a Fragment not attached to Activity error.

2.5 Array IndexOutOfBoundsException Corner Crossing Anomaly

  • A. Detailed crash log information

    • This exception represents an array crossover
    java.lang.ArrayIndexOutOfBoundsException: 0
        at com.example.mytest.CityAdapter.setDataNotify(CityAdapter.java:183)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  • B. View crash class information

    • Raises to indicate that an array has been accessed using an illegal index. The index is either negative or greater than or equal to the size of the array.
    public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
        private static final long serialVersionUID = -5116101128118950844L;
        public ArrayIndexOutOfBoundsException() {
            super();
        }
        public ArrayIndexOutOfBoundsException(int index) {
            super("Array index out of range: " + index);
        }
        public ArrayIndexOutOfBoundsException(String s) {
            super(s);
        }
        public ArrayIndexOutOfBoundsException(int sourceLength, int index) {
            super("length=" + sourceLength + "; index=" + index);
        }
        public ArrayIndexOutOfBoundsException(int sourceLength, int offset,
                int count) {
            super("length=" + sourceLength + "; regionStart=" + offset
                    + "; regionLength=" + count);
        }
    }
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • In this case, we usually need to make a good judgment of length before the array loop. When index exceeds the upper and lower limits of length, it will make an error. Examples are as follows: an array int test[N], which has N elements: test[0]~test[N-1]. If test[N] is called, an error will be reported. It is recommended that the length of the array (array.length) be not exceeded when reading.
    • A common scenario in Android is that the header in the pull-up refresh will also be the tenth position of the listview, and it is easy to cross the boundary if the judgment is wrong.
  • G. Other Extensions

2.6 Constructing method permission exception in IllegalAccessException method

  • A. Detailed crash log information

    Unable to instantiate application com.pedaily.yc.meblurry.App: java.lang.IllegalAccessException
  • B. View crash class information

    • IllegalAccessException is triggered when an application attempts to create instances (except arrays), set or acquire fields, or invoke methods reflectively, but the currently executed method cannot access the definition of the specified class, field, method, or constructor.
    public class IllegalAccessException extends ReflectiveOperationException {
        private static final long serialVersionUID = 6616958222490762034L;
        public IllegalAccessException() {
            super();
        }
        public IllegalAccessException(String s) {
            super(s);
        }
    }
  • C. Anomaly Analysis in Project

    • The error prompt is that the permission of the constructor is incorrect
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • After checking the whole Application, it was found that there was a parametric construction method, which was designed to be private. Modify it to public.
  • G. Other Extensions

    • Android Broadcast Receiver encountered a java.lang.Illegal Access Exception solution. The main reason for the error was that the default constructor was called elsewhere in app, and the default constructor had to be added with public access.

2.7 android. view. Windows Manager $BadTokenException, dialog window exception

  • A. Detailed crash log information

    Unable to add window -- token android.os.BinderProxy@9a57804 is not valid; is your activity running?
    android.view.ViewRootImpl.setView(ViewRootImpl.java:907)
  • B. View crash class information

    • This exception class can be found in Windows Manager, mainly triggered when trying to add views
    public static class BadTokenException extends RuntimeException {
        public BadTokenException() {
        }
    
        public BadTokenException(String name) {
            super(name);
        }
    }
  • C. Anomaly Analysis in Project

    • This exception indicates that a window cannot be added, usually because the view to which it is attached no longer exists.
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • There was a custom pop-up window in the previous project that occasionally reported this error. The solution is shown in the following code
    • The main logic is to add logic judgment to judge the existence of host activity when the window show or dismiss.
    /**
     * Display Loading Window
     * @param context               context
     * @param isCancel              Can we cancel it?
     */
    public static void show(Context context,  boolean isCancel) {
        if(context == null){
            return;
        }
        if (context instanceof Activity) {
            if (((Activity) context).isFinishing()) {
                return;
            }
        }
        if (loadDialog != null && loadDialog.isShowing()) {
            return;
        }
        loadDialog = new LoadLayoutDialog(context, isCancel);
        loadDialog.show();
    }
    
    /**
     * Destroy loading window
     * @param context               context
     */
    public static void dismiss(Context context) {
        if(context == null){
            return;
        }
        try {
            if (context instanceof Activity) {
                if (((Activity) context).isFinishing()) {
                    loadDialog = null;
                    return;
                }
            }
            if (loadDialog != null && loadDialog.isShowing()) {
                Context loadContext = loadDialog.getContext();
                if (loadContext instanceof Activity) {
                    if (((Activity) loadContext).isFinishing()) {
                        loadDialog = null;
                        return;
                    }
                }
                loadDialog.dismiss();
                loadDialog = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            loadDialog = null;
        }
    }
  • G. Other Extensions

    • Dialog & Alert Dialog, Toast, and Windows Manager often report this exception when they are not used correctly. There are many reasons. Several common scenarios are as follows:

      • 1. When there was no destroy on the previous page, the previous Activity had received the broadcast. If Activity before this time does UI level operation processing, it will cause crash. When refreshing the UI level, we must pay attention to the timing. We suggest using set_result instead of broadcasting to refresh, so as to avoid broadcasting. The code is not intuitive and error-prone.
      • 2.Dialog pops up after Actitivty exits. When Dialog calls show method for display, there must be an activity as the carrier of the window. If the activity is destroyed, the window carrier of Dialog can not be found. It is recommended to determine whether Activity has been destroyed before Dialog calls the show method.
      • 3. When the Service & Application pop-up dialog box or Windows Manager adds view, the window type is not set to TYPE_SYSTEM_ALERT. You need to add dialog. getWindow (). SetType (Windows Manager. LayoutParams. TYPE_SYSTEM_ALERT) before calling the dialog.show() method.
      • On the 4.6.0 system, if the suspension window is not granted permission, the problem will pop up. Settings.canDrawOverlays can be used to determine whether the permission is available.
      • 5. Some unstable MIUI System Bugs cause permission problems. The system regards Toast as a system-level bullet window. Android 6.0 system Dialog bullet window needs user's manual authorization. If app does not add SYSTEM_ALERT_WINDOW permission, this error will be reported. Need to add system Dialog pop-up window permission to app, and apply for permission dynamically. Failure to satisfy Article 1 will result in no permission flashback, and failure to satisfy Article 2 will result in no Toast.
  • H. Other suggestions

    • 1. Do not use dialog boxes in non-UI threads to create, display and cancel dialog boxes;
    • 2. Minimize the use of separate threads, start with real time-consuming operations using threads, threads do not directly use Java-style anonymous threads, unless it is a simple operation, operations do not need to do anything else.
    • 3. If dialog is operated in callbacks of asynchronous networks initiated in fragments, it is necessary to judge isAdd() before the operation, so as to avoid fragments being recycled, but dialog is also required to dismiss
    • 4. Close Dialog early in Activity on Destroy

2.8 java.lang.NoClassDefFoundError could not find class exception

  • A. Detailed crash log information
  • B. View crash class information

    • If a Java virtual machine or ClassLoader instance attempts to load the definition of a class (as part of a normal method call or as part of creating a new instance with a new expression), the definition of that class is thrown. A search class definition exists when compiling the currently executed class, but it cannot be found again.
    public class NoClassDefFoundError extends LinkageError {
        private static final long serialVersionUID = 9095859863287012458L;
        public NoClassDefFoundError() {
            super();
        }
        public NoClassDefFoundError(String s) {
            super(s);
        }
        private NoClassDefFoundError(String detailMessage, Throwable throwable) {
            super(detailMessage, throwable);
        }
    }
  • C. Anomaly Analysis in Project

    • The main reason for the problem is that the number of methods exceeds the limit of 65536. Due to the changing requirements in actual development, more and more open source frameworks are used, most of them use third-party SDK, resulting in the number of methods easily exceeding the 65536 limit. Error Java.lang.NoClassDefFoundError
  • D. Process analysis of triggering crash logs

    • This error is caused by the total number of methods used in Android applications. The Android platform's Java virtual machine Dalvik uses the native type short to index the method in the DEX file when executing the Java application in DEX format. This means that the total number of methods that a single DEX file can be referenced is limited to 65536. Usually APK contains a classes.dex file, so the total number of Android application methods can not exceed this number, which includes Android framework, class libraries and your own code. Android 5.0 and later uses a runtime called ART, which naturally supports loading multiple DEX files from APK files. When an application is installed, it performs precompilation, scans the classes(..N).dex file and compiles it into a single. oat file for execution.
  • F. Solutions

    • 64k Solution
  • G. Other Extensions

    • This exception indicates that a class definition cannot be found, and an error is thrown when a JVM or ClassLoader instance attempts to load the class definition (which is usually part of the process of creating an instance by a method call or a new expression) and the class definition is not found.
    • [Solution]: NoClassDefFoundError exceptions generally occur when the compilation environment is inconsistent with the runtime environment, that is, it is possible to change the Classpath or jar package after compilation, so that the JVM or ClassLoader cannot find the definition of this class during runtime.

      • 1. Subdex package programming, if the dependent dex package deletes the specified class, the initialization method will be wrong.
      • 2. When using third-party SDK or plug-in programming, failure of dynamic loading or instantiating classes will result in an error.
      • 3. When system resources are scarce, when a large number of class es need to be loaded into memory, they are in a competitive relationship, and some calss competitions fail, resulting in unsuccessful loading.
      • 4. Failure to load and initialize a class (such as static block throwing java.lang.ExceptionInInitializerError exception), and then referring to this class again will also prompt NoClassDefFoundErr error;
      • 5. Mobile phone system version or hardware device mismatch (e.g. ble device only supports SDK of more than 18), program reference class does not exist in low version, resulting in NoClassDefFoundErr error.
      • 6.so file can not be found, device platform armeabi-v7a, but my so library is placed in armeabi, the solution is to create a new armeabi-v7a package, and copy the armeabi file.

2.9 Android appears: Your project path contains non-ASCII characters.

  • A. Detailed crash log information
  • B. View crash class information
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • It's a good solution, that is, your project path or project name contains Chinese, just modify the relevant name.
  • G. Other Extensions

3.1 OnErrorNotImplementedException[ Can't create handler inside thread that has not called Looper.prepare()]

  • A. Detailed crash log information

    Can't create handler inside thread that has not called Looper.prepare()
  • B. View crash class information
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs

    • This is because the handler object is in the same thread as its caller, and if a delay operation is set in the handler, the calling thread will also block. Each Handler object binds to a Looper object, and each Looper object corresponds to a Message Queue. If the Looper object bound to the Handler is not specified when it is created, the system will bind the current thread's Looper to the Handler by default.
    • In the main thread, you can create a Handler object directly using new Handler(), which automatically binds to the Looper object of the main thread; in the non-main thread, you will get an error if you create a Handler directly, because the Android system does not open Looper in the non-main thread by default, and the Handler object must bind to the Looper object.
    • If the handler is created in the main thread, the system will automatically create the Looper, but when the handler is created in the sub-thread, the Looper will not be created automatically. If the handler is not created manually, the system will crash.
  • F. Solutions

    • Don't do UI operations in sub-threads, such as changing the interface, toast, etc.
    • Method 1: Looper (Looper. prepare () - > Looper. loop () needs to be manually opened in this thread, and then bound to the Handler object.
    final Runnable runnable = new Runnable() {
      @Override
      public void run() {
        //Perform time-consuming operations
        try {
    
          Log.e("bm", "runnable Threads: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
    
          Thread.sleep(2000);
          Log.e("bm", "Execute time-consuming operations~");
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
      }
    };
    new Thread() {
      public void run() {
        Looper.prepare();
        new Handler().post(runnable);//Go directly to a new handler in a sub-thread
        Looper.loop();    //In this case, the Runnable object runs in a sub-thread and can be networked, but the UI cannot be updated.
      }
    }.start();
    • Method 2: Get the Loper of the main thread through Looper.getMainLooper(), and bind it to the Handler object.
    final Runnable runnable = new Runnable() {
      @Override
      public void run() {
        //Perform time-consuming operations
        try {
          Log.e("bm", "runnable Threads: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
          Thread.sleep(2000);
          Log.e("bm", "Execute time-consuming operations~");
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
      }
    };
    new Thread() {
      public void run() {
          //Go directly to a new handler in a sub-thread
        new Handler(Looper.getMainLooper()).post(runnable);
        //In this case, the Runnable object runs in the main thread and cannot be networked, but the UI can be updated.
      }
    }.start();
  • G. Other Extensions

3.2 platform-toolsadb.exe,start-server' failed -- run manually if necessary

  • A. Detailed crash log information
  • B. View crash class information
  • C. Anomaly Analysis in Project

    • The adb failed to start and the port was occupied
  • D. Process analysis of triggering crash logs
  • F. Solutions

    Baidu google people say that task manager kill s ADB or restarts adb server, but my task manager does not have adb, guess is that a program occupies the ADB port. So look it up in this way.
    5037 is the default port of adb to view the port as follows:
    netstat -aon|findstr "5037"
    TCP 127.0.0.1:5037 0.0.0.0:0 LISTENING 6540
     Discover that 6540 occupies 5037 port, continue to look at 6540 task, found wandoujia. As follows
    tasklist|findstr "6540"
    wandoujia_daemon.exe 6540 Console 1 4,276 K
    
    Next, the problem is solved by kill ing wandoujia_daemon.exe in the task manager and running the android program, ok.
    
    1. Close the xx pod process
    2.adb kill-server
    3.adb start-server
  • G. Other Extensions

3.3 java.lang.IllegalStateException: ExpectedBEGIN_OBJECT but was STRING at line 1 column 1 path $

  • A. Detailed crash log information

    • Illegal parameters should start reading with {} brackets, so String strings need to be processed, which may not be standard json data.
    java.lang.IllegalStateException: ExpectedBEGIN_OBJECT but was STRING at line 1 column 1 path $
  • B. View crash class information
  • C. Anomaly Analysis in Project

    • Gson parsing data problems, because the server returned data is not rigorous
  • D. Process analysis of triggering crash logs

    • Possible mistakes:

      • The bean class field type and field name are inconsistent.
      • The strings accessed by the server are not pure json with spaces and carriage return characters (hard to find).
      • If the accessed json string is not utf-8 encoding, this problem will arise with Gson parsing. Printing in the log will find that there are scrambled characters in front of json {}, which also needs attention. This is due to different encoding reasons, so you have to access the json string of utf-8 to reduce this problem.
    • Problem may be: Strings are not pure json strings. They may start with empty characters or carriage return characters. This is a server problem, but we can also solve it.
    • The most important reason is that the result of our network request is a string, not a json, so it needs to be processed.
  • F. Solutions

    /**
*/
public static boolean isJson(String value) {
    try {
        new JSONObject(value);
    } catch (JSONException e) {
        return false;
    }
    return true;
}

/**
* Judging whether it is a json structure
*/
public static boolean isGoodJson(String json) {
    try {
        new JsonParser().parse(json);
        return true;
    } catch (JsonParseException e) {
        System.out.println("bad json: " + json);
        return false;
    }
}
```
  • G. Other extensions, supplementary notes

    • Solution: Background output stable Gson format. This method works too much.
    • The real problem is my data structure.
    • For example, the following Json string:
    • {"code":1,"info":"success","results":{"id":"1","name":"hehe"}}
    • results should correspond to an entity class. If you want to parse it into String or List at this time, an exception will occur.
    • If you refer to the data model processed with GsonForm, there is almost no problem; adding the result may cause format changes in the request for some reason, at which point there is a risk of the exception. In Gson, the content caused by "" appearing after the keyword will be regarded as STRING only, "{}" as class only, and "[]" as List only, which is almost mandatory.
    • That is, if your entity expects to get String variables, but the corresponding "{" or "[" appears after the keyword, then the transformation will be considered wrong and throw an exception.

3.4 android.content.ActivityNotFoundException: No Activity found to handle Intent

  • A. Detailed crash log information

    android.content.ActivityNotFoundException: No Activity found to handle Intent
  • B. View crash class information

    • When the call {@link Context#startActivity} or one of its variants fails, this exception is raised because the activity executing the given intent cannot be found.
    public class ActivityNotFoundException extends RuntimeException
    {
        public ActivityNotFoundException()
        {
        }
    
        public ActivityNotFoundException(String name)
        {
            super(name);
        }
    };
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • The first way: do a try catch
    Intent intent = new Intent(Intent.ACTION_SENDTO,url);
    try {
        context.startActivity(intent);
    } catch(ActivityNotFoundException exception) {
        Toast.makeText(this, "no activity", Toast.LENGTH_SHORT).show();
    }
    • The second way is to judge whether there is an app client.
    //Avoid users who install App Po clicking on other external links to go this way leading to crash
    //Judging whether to use APO Client
    if(AppUtils.isPkgInstalled(AdDetailActivity.this,"com.tencent.android.qqdownloader")){
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        startActivity( intent);
    }

3.5 Package manager has died leading to crash

  • A. Detailed crash log information

    Error code location
    public static String softVersionName(Context context) {
        PackageInfo info = null;
        try {
            info = context.getPackageManager().getPackageInfo( context.getPackageName(), 0);     //Ad locum
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return info.versionName;
    }
  • B. View crash class information
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs

    • Cause analysis (caused by Binder)
    • If the Binder content used in a process exceeds 1M, it will crash.
    • If the use of Binder exceeds the limit of a process, the exception TransactionTooLargeException is thrown.
    • Runtime Exception is thrown if Binder crash is caused for other reasons.
  • F. Solutions

    public static String softVersionName(Context context) {
        PackageInfo info = null;
        try {//Adding Synchronization Block
            synchronized (context) {
                info =context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            }
            return info.versionName;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
  • G. Other Extensions

    private void test() {
            //This Demo is to create two threads at the same time to make a Binder call.
            for (int i = 0; i < 2; i++) {
                new Thread() {
                    @Override
                    public void run() {
                        int count = 0;
                        List<PackageInfo> list = getPackageManager().getInstalledPackages(0);
                        for (PackageInfo info : list) {
                            if(count >=1000){
                                break;
                            }
                            try {
                                PackageInfo pi = getPackageManager().getPackageInfo(info.packageName, PackageManager.GET_ACTIVITIES);
                            } catch (PackageManager.NameNotFoundException e) {
    
                            }
                        }
                    }
                }.start();
            }
        }
    }
    • Error Printing Log
    • Solution: In fact, as long as you avoid multiple threads calling Binder at the same time, after all, a thread will be released, so it is theoretically difficult to happen.
    synchronized(MainActivity.class){ 
        PackageInfo pi = getPackageManager() .getPackageInfo(info.packageName, PackageManager.GET_ACTIVITIES); 
    } 

3.6 Illegal ArgumentException View Add Window Error

  • A. Detailed crash log information

    View=com.android.internal.policy.impl.PhoneWindow$DecorView{22a4fb16 V.E..... R.....ID 0,0-1080,1020} not attached to window manager
    com.flyco.dialog.widget.base.BaseDialog.superDismiss(BaseDialog.java)
  • B. View crash class information
  • C. Anomaly Analysis in Project

    • This exception indicates that view is not added to the window manager. Usually when we dismiss the dialog box, activity no longer exists. It is recommended that dialog boxes should not be operated on non-UI threads.
  • D. Process analysis of triggering crash logs

    • This kind of Exception often happens when there is a time-consuming thread operation that needs to display a Dialog, a dialog box at the beginning of the task, and then when the task is completed in the Dismiss dialog box, if during this period Activity is killed for some reason and restarted, then when dialog tone When using dismiss, Windows Manager checks to find that Activity to which Dialog belongs no longer exists, so it will report an error. To avoid such Exceptions, dialog boxes and threads should be used correctly
  • F. Solutions

    • Refer to 1.7 in the crash bug log summary 1.
  • G. Other extensions, suggestions

    • Do not use dialog boxes to create, display and cancel dialog boxes in non-UI threads.
    • Leave as few separate threads as possible, and start with real time-consuming operations using threads. Threads should not use Java-style anonymous threads directly, unless it is a simple operation, the operation does not need to do anything else.
    • If dialog operation is performed in callbacks of asynchronous networks initiated in fragments, then isAdd() needs to be judged before operation to avoid fragments being recycled, but dialog is also required to dismiss
    • Close Dialog early in Activity on Destroy

3.7 Illegal State Exception: Not allowed to start service Intent exception crash

  • A. Detailed crash log information

     Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { act=initApplication cmp=com.paidian.hwmc/.service.InitializeService }: app is in background uid UidRecord{a37d28d u0a386 TRNB bg:+5m30s482ms idle procs:3 seq(0,0,0)}
  • B. View crash class information
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs
  • F. Solutions
  • G. Other Extensions

3.8 java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

  • A. Detailed crash log information

  • B. View crash class information
  • C. Anomaly Analysis in Project

    • From the source code analysis below, we can see that the reason for the above crash log is that when we press the page return key, the current Activity and the execution of the destruction operation (that is, we used to call the finish method elsewhere).
  • D. Process analysis of triggering crash logs

    • The problem is the Activity onBackPressed () method. View the source code: click super in the onBackPressed method
    • In FragmentActivity
    @Override
    public void onBackPressed() {
        if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) {
            super.onBackPressed();
        }
    }
    • Then click super again, in Activity
    public void onBackPressed() {
        if (mActionBar != null && mActionBar.collapseActionView()) {
            return;
        }
    
        if (!mFragments.getFragmentManager().popBackStackImmediate()) {
            finishAfterTransition();
        }
    }
    public void finishAfterTransition() {
        if (!mActivityTransitionState.startExitBackTransition(this)) {
            finish();
        }
    }
    • We see that the onBackPressed() method performs two operations. The first is to get the current FragmentManager and perform the de-stack operation. The second is to perform the finish method after the de-stack is completed. Continuing with the source code, the key is the popBackStackImmediate method of the FragmentManager implementation class
    @Override
    public boolean popBackStackImmediate() {
        checkStateLoss();
        executePendingTransactions();
        return popBackStackState(mHost.getHandler(), null, -1, 0);
    }
    • As we can see, there is one more step to check the operation before performing the unwind action.
    private void checkStateLoss() {
        if (mStateSaved) {
            throw new IllegalStateException(
                    "Can not perform this action after onSaveInstanceState");
        }
        if (mNoTransactionsBecause != null) {
            throw new IllegalStateException(
                    "Can not perform this action inside of " + mNoTransactionsBecause);
        }
    }
    • From here, we finally found the exception copy on the crash log: Can not perform this action after onSave Instance State
  • F. Solutions

    • In scenario 1, when invoking super.onBackPressed, we need to determine whether the current Activity is executing a destruction operation.
    if (!isFinishing()) {
        super.onBackPressed();
    }
    • Scheme 2, through the source code analysis above, we also know that super.onBackPressed finally calls finish() method, so we can rewrite onBackPressed and call finish method directly.
  • G. Other Extensions

3.9 In Fragment, the context is not found through getActivity, and null causes null pointer exceptions

  • A. Detailed crash log information
  • B. View crash class information
  • C. Anomaly Analysis in Project

    • Using ViewPager+Fragment for view sliding, we may need to use context Context (e.g. basic Toast) in some parts of logic, but since Fragment is just an attempt to get clothes in the Activity container, if we need to get the context context of the current Activity, we must get it through getActivity().
    • When getActivity() appears null, it causes the program to report a null pointer exception. Actually, the reason can be attributed to the fact that we are here.

      • When switching fragment s, they are crash frequently
      • Insufficient system memory
      • When switching between horizontal and vertical screens
      • All of the above will lead to Activity being recycled by the system, but because the life cycle of fragment s will not be recycled with Activty being recycled, it will lead to null problem of getActivity().
    • Many people have been troubled by this problem. If the app runs in the background for a long time, crash may occur when it enters the app again, and fragments may overlap. If the system is short of memory, switching screen and app runs in the background for a long time, Activity may be reclaimed and rebuilt by the system, but Fragments will not be reclaimed as Activity is reclaimed. All fragments created will be saved in Bundle, resulting in Fragments losing the corresponding Activity.
  • D. Process analysis of triggering crash logs

    • When you encounter getActivity() as null, or getContext(), calm down and think about the following three points:

      • 1. Is it in the third party's callback?
      • 2. Is it invoked in other processes (the first point is actually invoked in other processes)
      • 3. Is the call not within the specified lifecycle (between onAttach and onDetach)
  • F. Solutions

    stay Fragment In direct call
    private MActivity mActivity; 
    @Override 
    public void onAttach(Activity activity) { 
        super.onAttach(activity); 
        mActivity = (MActivity) activity; 
    }
    @Override
    public void onDetach() {
        super.onDetach();
        mActivity = null;
    }
  • G. Other Extensions

    • Source Code Interpretation: In FragmentActivity
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Parcelable p = mFragments.saveAllState();
        if (p != null) {
            outState.putParcelable(FRAGMENTS_TAG, p);
        }
        ......
    }
    • If you click on our application from a recently used application, the system will restore Activeness that was previously recycled, and Fragment Activity will also restore Fragments in oncreate.
    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);
        super.onCreate(savedInstanceState);
        NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            mFragments.restoreLoaderNonConfig(nc.loaders);
        }
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
      ......
        }
        if (mPendingFragmentActivityResults == null) {
            mPendingFragmentActivityResults = new SparseArrayCompat<>();
            mNextCandidateRequestIndex = 0;
        }
        mFragments.dispatchCreate();
    }
    • Suppose our page is called MyActivity (inherited from Fragment Activity), and the fragment used in it is called MyFragment. When this happens, app changes as follows:

      • 1. MyActivity is recycled in several cases mentioned above.
      • 2. Save the status of MyFragment through onSave InstanceState
      • 3. Users click on app again
      • 4. Because MyActivity is recycled, the system restarts MyActivity and restores fragment according to the status of previously saved MyFragment.
      • 5. In MyActivity's code logic, a new MyFragment is created again
      • 6. Page confusion, covering two layers of fragment s. If the restored MyFragment uses the getActivity() method, a null pointer exception is reported.
    • For the above problems, the following two solutions can be considered:

      • 1. Do not save fragments: Rewrite the onSaveInstanceState method in MyActivity, annotate the super.onSaveInstanceState(outState), so that it no longer saves the fragments state, so as to achieve the purpose of fragments destroyed with MyActivity.
      • 2. Clear the fragment status when rebuilding: Clear the fragment status data in Bundle before restoring the fragment. The methods are as follows:
      if(savedInstanceState!= null){
          String FRAGMENTS_TAG =  "Android:support:fragments";
          savedInstanceState.remove(FRAGMENTS_TAG);
      }

4.1 Illegal ArgumentException crashes [url address passes in illegal parameters, escape characters]

  • A. Detailed crash log information

  • B. View crash class information
  • C. Anomaly Analysis in Project

    • Only a small number of illegal parameters are passed in to cause crashes, and conventional methods cannot be used directly. Need to filter
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • Java calls URLDecoder.decode(str,"UTF-8"); throws the above exception, the main reason is that% is a special character in the URL and needs special escape.
    public static String replacer(String data) {
        try {
            //Replace the% number in the string with% 25
            data = data.replaceAll("%(?![0-9a-fA-F]{2})", "%25");      
            data = URLDecoder.decode(data, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return data;
    }

4.2 ClassNotFoundException: Didn't find class "" on path: /data/app/* error

  • A. Detailed crash log information

    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{*****Activity}: java.lang.ClassNotFoundException: Didn't find class "*****Activity" on path: /data/app/*******.apk
  • B. View crash class information

    • Raised when an application attempts to load a class with a string name: but the definition of a class with a specified name cannot be found. Since version 1.4, this exception has been modified to conform to the general exception linking mechanism. The "optional exception raised when loading a class" provided at build time and accessed through the {@link#getException()} method is now called cause, and can be accessed through the {@link Throwable#getCace()} method and the "legacy method" mentioned earlier.
    public class ClassNotFoundException extends ReflectiveOperationException {
        private static final long serialVersionUID = 9176873029745254542L;
        private Throwable ex;
        public ClassNotFoundException() {
            super((Throwable)null);  // Disallow initCause
        }
        public ClassNotFoundException(String s) {
            super(s, null);  //  Disallow initCause
        }
        public ClassNotFoundException(String s, Throwable ex) {
            super(s, null);  //  Disallow initCause
            this.ex = ex;
        }
        public Throwable getException() {
            return ex;
        }
        public Throwable getCause() {
            return ex;
        }
    }
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • 1. The name of Activity registered in Manifest file, whether it has been written incorrectly, whether the package name has been wrong, some netizens may only write a class name, which is replaced by a dot, but this class is not in the default package, so report this error, then just write the full name of the class.
    • 2. The class you use is an external JAR package. When compiled and used in a project, the published APK does not contain JAR files. Therefore, when APK is executed, it will not find JAR files and will report errors. Some Androids need some third-party packages. It was possible to introduce them directly in the past, but not in the latest adt. It is necessary to create a new libs folder in the program and copy the third-party jar files into the libs folder. Many people make mistakes because of this, especially in the previous projects, default and There is no libs folder, but with the new version of adt, the libs folder is built by default.
    • 3. It's also important that in Order and Export under the Java Build Path panel, be sure to tick the jar file you introduced, otherwise, just like no reference, remember.

4.3 NoClassDefFoundError exception [which indicates that the class definition cannot be found]

  • A. Detailed crash log information

    • Often encounter errors such as java.lang.NoClassDefFoundError, it takes a lot of time to find the cause of the error, which class is missing? Class Mingming is still there. Why can't we find it? And it's easy to confuse the two errors of java. lang. NoClassDefFoundError and java.lang.ClassNotfoundException, which are actually completely different.
  • B. View crash class information
  • C. Anomaly Analysis in Project

    • This exception indicates that a class definition cannot be found, and an error is thrown when a JVM or ClassLoader instance attempts to load the class definition (which is usually part of the process of creating an instance by a method call or a new expression) and the class definition is not found.
    • NoClassDefFoundError occurs because the Java Virtual Machine can find the right class at compile time, but not at run time.
    • For example, when we want to call a method of a class or access its static members at runtime, we find that the class is not available, and the Java Virtual Machine throws a NoClassDefFoundError error.
    • Summary: This error is that the compiler is available and the runtime is unavailable.
  • D. Process analysis of triggering crash logs

    • The corresponding Class is not available in java's classpath
    • You may run your program with the jar command, but the class is not defined in the classpath attribute in the manifest file of the jar file
    • The startup script of a possible program overrides the original classpath environment variable
    • Because NoClassDefFoundError is a subclass of java.lang.LinkageError, it may be caused by the unavailability of native class libraries for program dependencies.
    • Check for errors like java.lang.ExceptionInInitializer Error in the log file. NoClassDefFoundError may be caused by static initialization failure
  • F. Solutions

    • When a jar file is missing, or the jar file is not added to the classpath, or a change in the name of the jar file causes a java.lang.NoClassDefFoundError error.
    • Since NoClassDefFoundError is a subclass of Linkage Error, and Linkage Error errors occur when relying on other classes, it is possible to have a java.lang.NoClassDefFoundError if your program relies on native class libraries and the required dll does not exist. This error may also throw exceptions such as java.lang.UnsatisfiedLinkError: no dll in java.library.path Exception Java. The solution is to put the dependent libraries and DLLs together with your jar package.
    • If you use Ant build scripts to generate jar files and manifest files, make sure that Ant scripts get the correct classpath values written to the manifest.mf file
    • The permission problem of Jar files may also lead to NoClassDefFoundError. If your program runs on a multi-user operating system like linux, you need to assign the permissions of related resource files, such as Jar files, class library files and configuration files, to the user group of the program, if you use multiple users. When jar packages are shared by different programs, it is easy to have privilege problems. For example, if other users use the jar package with their own permissions, your program will not have permission to access, which will lead to errors in java.lang.NoClassDefFoundError.
    • Programs based on XML configuration can also lead to errors in NoClassDefFoundError. For example, most Java frameworks like Spring and Struts use XML configuration to get the corresponding bean information. If you enter the wrong name, the program may load other wrong classes and cause NoClassDefFoundError exceptions. When we use Spring MVC framework or Apache Struts framework, we often have Exception in thread "main" java.lang.NoClassDefFoundError when deploying War files or EAR files.
  • G. Other extensions, common scenarios

    • 1. Subdex package programming, if the dependent dex package deletes the specified class, the initialization method will be wrong.
    • 2. When using third-party SDK or plug-in programming, failure of dynamic loading or instantiating classes will result in an error.
    • 3. When system resources are scarce, when a large number of class es need to be loaded into memory, they are in a competitive relationship, and some calss competitions fail, resulting in unsuccessful loading.
    • 4. Failure to load and initialize a class (such as static block throwing java.lang.ExceptionInInitializerError exception), and then referring to this class again will also prompt NoClassDefFoundErr error;
    • 5. Mobile phone system version or hardware device mismatch (e.g. ble device only supports SDK of more than 18), program reference class does not exist in low version, resulting in NoClassDefFoundErr error.
    • 6.so file can not be found, device platform armeabi-v7a, but my so library is placed in armeabi, the solution is to create a new armeabi-v7a package, and copy the armeabi file.
  • Differences between H.NoClassDefFoundError and lassNotFoundException

    • NoClassDefFoundError happens when the JVM is running dynamically. According to the class name you provide, you can find the corresponding class in the classpath to load. But when it can't find the class, the error of java.lang.NoClassDefFoundError happens.
    • ClassNotFoundException is an error that occurs when the corresponding class is not found in the classpath at compilation time

4.4 The previous project used customer service udesk, and initialization after sdk update caused crash problem.

  • Cause of error: Initialize udesk customer service sdk, need to pass in token, name and other information. Token is the unique identification of customers, and customer service third party SDK creates sqlite database by token name, which causes the database name to be too long...
  • Error reporting information:

    Could not open database, (OS error - 36:File name too long)
    {"code":"4444","message":"unknown error","exception":"Data too long for column 'sdk_token' at row 1"}
  • Log error screenshot

  • Solution

    • The first solution: the client clips the top 10 (or 15) strings of token as the unique identifier of the customer. After testing, the problem can be solved, but it needs to be distributed, and the problem of the previous version can not be corrected.
    • The second solution: third-party platform solution, because there was no problem with the previous use, and then there was the problem. Maybe they changed the code to cause the problem! I've already sent a message to a third party. Look at it on Monday.

4.5 java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception

  • A. Detailed crash log information

    Caused by: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
    Caused by: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
  • B. View crash class information

    public class ExecutionException extends Exception {
        protected ExecutionException() {
            throw new RuntimeException("Stub!");
        }
    
        protected ExecutionException(String message) {
            throw new RuntimeException("Stub!");
        }
    
        public ExecutionException(String message, Throwable cause) {
            throw new RuntimeException("Stub!");
        }
    
        public ExecutionException(Throwable cause) {
            throw new RuntimeException("Stub!");
        }
    }
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • In the project, just add a line of code to the gradle.properties file, that is, gradle.properties(Project properties)
    android.enableAapt2=false
  • G. Other Extensions

    • What is configured in gradle.properties can be directly referenced in the gradle file
    • The gradle.properties file configuration in the project root directory:
    # Application version name
    VERSION_NAME=1.0.0
    # Application Version Number
    VERSION_CODE=100
    # Support library version
    SUPPORT_LIBRARY=24.2.1
    # MIN_SDK_VERSION
    ANDROID_BUILD_MIN_SDK_VERSION=14
    # TARGET_SDK_VERSION
    ANDROID_BUILD_TARGET_SDK_VERSION=24
    # BUILD_SDK_VERSION
    ANDROID_BUILD_SDK_VERSION=24
    # BUILD_TOOLS_VERSION
    ANDROID_BUILD_TOOLS_VERSION=24.0.3
    • At this point, build.gradle, which configures app and lib, can write as follows:
    android {
        compileSdkVersion project.ANDROID_BUILD_SDK_VERSION as int
        buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
     
        defaultConfig {
            applicationId project.APPLICATION_ID // The lib project does not need to configure this item
            versionCode project.VERSION_CODE as int
            versionName project.VERSION_NAME
            minSdkVersion project.ANDROID_BUILD_MIN_SDK_VERSION as int
            targetSdkVersion project.ANDROID_BUILD_TARGET_SDK_VERSION as int
        }
    }
     
    dependencies {
        compile fileTree(include: ['*.jar'], dir: 'libs')
        //Note here that there are double quotation marks.
        compile "com.android.support:appcompat-v7:${SUPPORT_LIBRARY}"
        compile "com.android.support:design:${SUPPORT_LIBRARY}"
        compile "com.android.support:recyclerview-v7:${SUPPORT_LIBRARY}"
        compile "com.android.support:support-annotations:${SUPPORT_LIBRARY}"
        compile "com.android.support:cardview-v7:${SUPPORT_LIBRARY}"
        compile "com.android.support:support-v4:${SUPPORT_LIBRARY}"
    }

4.6 java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException

  • A. Detailed crash log information

    • Execution exception, process exception.
    Caused by: java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException: Error while executing process /Users/duanzheng/WorkSpace/AndroidSdk/build-tools/27.0.3/aapt with arguments {package -f --no-crunch -I /Users/duanzheng/WorkSpace/AndroidSdk/platforms/android-27/android.jar -M /Users/duanzheng/.jenkins/workspace/android_hwmc_project/UdeskSDKUI/build/intermediates/manifests/aapt/release/AndroidManifest.xml -S /Users/duanzheng/.jenkins/workspace/android_hwmc_project/UdeskSDKUI/build/intermediates/res/merged/release --non-constant-id -0 apk --no-version-vectors}
    
    Caused by: org.gradle.process.internal.ExecException: Process 'command '/Users/duanzheng/WorkSpace/AndroidSdk/build-tools/27.0.3/aapt'' finished with non-zero exit value 1
    
    
    //Note the emphasis here: aapt''finished with non-zero exit value 1
  • B. View crash class information
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs
  • F. Solutions

    • The first method of online search: Preliminary guess may be caused by synchronized build files that are not needed. clean the project to see if it can be solved.
  • What is H.aapt?

4.7 00768556/vendor/lib/libllvm-glnext.so [armeabi-v8] Failure to load so libraries resulted in crash

  • A. Detailed crash log information

    • Meizu cell phone, once opened, it collapsed. Think about [armeabi-v8]?
    1 #00 pc 00768556 /vendor/lib/libllvm-glnext.so [armeabi-v8]
    2 #01 pc 000011e0 <unknown>
    3 java:
    4 [Failed to get java stack] 
  • B. View crash class information
  • C. Anomaly Analysis in Project
  • D. Process analysis of triggering crash logs
  • F. Solutions
  • G. Other Extensions

4.8 Only the original thread that created a view hierarchy can touch its views

  • A. Detailed crash log information

    UncaughtException detected: io.reactivex.exceptions.OnErrorNotImplementedException: Only the original thread that created a view hierarchy can touch its views.
    Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: 
    Only the original thread that created a view hierarchy can touch its views.
  • B. View crash class information

    • Exceptions mean that only the thread that created the view can operate on the view, which is generally thought to occur when the view is created in a non-UI thread.
  • C. Anomaly Analysis in Project

    • The related view and control operations in Android are not thread-safe, so Android will prohibit updating UI in non-UI threads. For explicit illegal operations, such as creating sub-threads directly in Activity and then operating UI directly in sub-threads, Android will exit abnormally and prompt should run on UIThread. Class error log information.
    • For implicit illegal operations, App does not simply and roughly exit abnormally, but with strange results. Only the original thread that created a view hierarchy can touch its views is an example. Literally, only the original thread that created the view hierarchy can operate its View, which is obviously thread-safe. All relevant.
  • D. Process analysis of triggering crash logs

    • This problem occurs when a notification is sent in intentService to update the data refresh on the shopping cart page.
  • F. Solutions
  • G. Other Extensions

4.9 NoSuchMethodException android.support.v4.app.Fragment$InstantiationException

  • Detailed log error

    vity.baojia.ChoiceResultPsActivity}: android.support.v4.app.Fragment$InstantiationException: 
    Unable to instantiate fragment com.cheoo.app.fragment.choiceresultps.QuotationDaQuanFragment: 
    could not find Fragment constructor
  • Analysis of the possible causes of the bug

    • The problem is mainly related to Activity's data recovery, which may produce Exception: android.support.v4.app.Fragment$InstantiationException.
    • Each Fragment must have a parametric-free construction method so that it can be instantiated when Activity restores its state.
    • It is strongly recommended that subclasses of Fragments do not have other parametric constructors, because these constructors will not be invoked when Fragments are re-instantiated. Instead, set parameters through setArguments(Bundle), and get parameters through getArguments. If there is no parametric construction method for Fragment, crash will occur when app restores Activity, such as rotating devices.
  • The problem code is shown below. The solution is to add a parameter-free constructor.

    public static BusinessHotCarFragment newInstance(Map<String,String> map) {
        BusinessHotCarFragment fragment = new BusinessHotCarFragment(map);
        return fragment;
    }
    
    public BusinessHotCarFragment(Map<String,String> map) {
        this.pMap =map;
    }
    
    //Solution to the problem by adding a parametric construction method
    public BusinessHotCarFragment(){}
  • Deep analysis of why Fragment s need parametric constructors to instantiate

    • Since the report can't find the error of the constructor, let's first look at the constructor of Fragment:

      • You can see from Google's translation. There is a comment on the constructor: the default constructor. Each fragment must have an argument-free constructor so that it can be instantiated when Activity restores state. It is strongly recommended that subclasses of fragments do not have other parametric constructors, because these parametric constructors are not called when fragments are re-instantiated; if values are to be passed, the setArguments method should be used, and the getArguments method should be called when these values need to be obtained.
      /**
       * Default constructor.  <strong>Every</strong> fragment must have an
       * empty constructor, so it can be instantiated when restoring its
       * activity's state.  It is strongly recommended that subclasses do not
       * have other constructors with parameters, since these constructors
       * will not be called when the fragment is re-instantiated; instead,
       * arguments can be supplied by the caller with {@link #setArguments}
       * and later retrieved by the Fragment with {@link #getArguments}.
       *
       * <p>Applications should generally not implement a constructor. Prefer
       * {@link #onAttach(Context)} instead. It is the first place application code can run where
       * the fragment is ready to be used - the point where the fragment is actually associated with
       * its context. Some applications may also want to implement {@link #onInflate} to retrieve
       * attributes from a layout resource, although note this happens when the fragment is attached.
       */
      public Fragment() {
      }
    • Where did this anomaly come from?

      • This comment clearly tells us that using parametric constructors can cause problems. It is recommended to use parametric constructors, but it does not tell us exactly where the problem is. We searched for the exception that could not find Fragment constructor in the Fragment source code and found that it was thrown in the instantiate method.
      • Looking at the code above, we can see that Fragment instantiates an object by calling the getConstructor() method of the class object to get the constructor object and calling its newInstance() method to create the object. The args parameter is also set to Fragment.
      public static Fragment instantiate(Context context, String fname, @Nullable Bundle args) {
          try {
              Class<?> clazz = sClassMap.get(fname);
              if (clazz == null) {
                  // Class not found in the cache, see if it's real, and try to add it
                  clazz = context.getClassLoader().loadClass(fname);
                  sClassMap.put(fname, clazz);
              }
              Fragment f = (Fragment) clazz.getConstructor().newInstance();
              if (args != null) {
                  args.setClassLoader(f.getClass().getClassLoader());
                  f.setArguments(args);
              }
              return f;
          } catch (ClassNotFoundException e) {
              throw new InstantiationException("Unable to instantiate fragment " + fname
                      + ": make sure class name exists, is public, and has an"
                      + " empty constructor that is public", e);
          } catch (java.lang.InstantiationException e) {
              throw new InstantiationException("Unable to instantiate fragment " + fname
                      + ": make sure class name exists, is public, and has an"
                      + " empty constructor that is public", e);
          } catch (IllegalAccessException e) {
              throw new InstantiationException("Unable to instantiate fragment " + fname
                      + ": make sure class name exists, is public, and has an"
                      + " empty constructor that is public", e);
          } catch (NoSuchMethodException e) {
              throw new InstantiationException("Unable to instantiate fragment " + fname
                      + ": could not find Fragment constructor", e);
          } catch (InvocationTargetException e) {
              throw new InstantiationException("Unable to instantiate fragment " + fname
                      + ": calling Fragment constructor caused an exception", e);
          }
      }
    • Where did this exception trigger?

      • The specific error was found, but where did the method call the trigger? Where Fragment did not find the call, since Fragment was managed by Fragment Manager, this type of discovery was invoked in the restoreAllState method.
      • This method is named to restore all states, annotated to create a list of active Fragments and instantiate them from saved states. This method should be called when Fragment is re-instantiated. This method is called in Fragment's restoreChildFragmentState.
      void restoreAllState(Parcelable state, FragmentManagerNonConfig nonConfig) {
          // Build the full list of active fragments, instantiating them from
          // their saved state.
          mActive = new SparseArray<>(fms.mActive.length);
          for (int i=0; i<fms.mActive.length; i++) {
              FragmentState fs = fms.mActive[i];
              if (fs != null) {
                  FragmentManagerNonConfig childNonConfig = null;
                  if (childNonConfigs != null && i < childNonConfigs.size()) {
                      childNonConfig = childNonConfigs.get(i);
                  }
                  ViewModelStore viewModelStore = null;
                  if (viewModelStores != null && i < viewModelStores.size()) {
                      viewModelStore = viewModelStores.get(i);
                  }
                  Fragment f = fs.instantiate(mHost, mContainer, mParent, childNonConfig,
                          viewModelStore);
                  if (DEBUG) Log.v(TAG, "restoreAllState: active #" + i + ": " + f);
                  mActive.put(f.mIndex, f);
                  // Now that the fragment is instantiated (or came from being
                  // retained above), clear mInstance in case we end up re-restoring
                  // from this FragmentState again.
                  fs.mInstance = null;
              }
          }
      ...   
      }
    • Then take a look at the restoreChildFragmentState method source code in Fragment.

      • The restoreChildFragmentState method is also called in the onCreate method of Fragment, where the saved InstanceState state is passed to restoreChildFragmentState to complete the re-instantiation of Fragment.
      void restoreChildFragmentState(@Nullable Bundle savedInstanceState) {
          if (savedInstanceState != null) {
              Parcelable p = savedInstanceState.getParcelable(
                      FragmentActivity.FRAGMENTS_TAG);
              if (p != null) {
                  if (mChildFragmentManager == null) {
                      instantiateChildFragmentManager();
                  }
                  mChildFragmentManager.restoreAllState(p, mChildNonConfig);
                  mChildNonConfig = null;
                  mChildFragmentManager.dispatchCreate();
              }
          }
      }
    • Then look at the onCreate method in Fragment

      @CallSuper
      public void onCreate(@Nullable Bundle savedInstanceState) {
          mCalled = true;
          restoreChildFragmentState(savedInstanceState);
          if (mChildFragmentManager != null
                  && !mChildFragmentManager.isStateAtLeast(Fragment.CREATED)) {
              mChildFragmentManager.dispatchCreate();
          }
      }
    • Come to conclusion

      • After the above analysis, we can see why this error occurred in Fragment's parametric constructor. Because when a Fragment is recreated for some reason, it calls the state saved before the onCreate method is passed in. In the instantiate method, a Fragment is created by reflecting the parametric constructor and initializing the Arguments to the original saved value. If there is no parametric constructor, an exception is thrown. The program crashes.

Other presentations

01. Summary of blog links

02. About my blog

Blog open source to GitHub, more to see: https://github.com/yangchong2...

Keywords: Java Fragment Android JSON

Added by vmarellano on Wed, 07 Aug 2019 18:11:53 +0300