Android Exceptions without Force Close

2020-08-07 03:01发布

问题:

I might be missing something, but whenever an Exception gets thrown in Android (or java), my application ALWAYS force closes, and the whole program is terminated. However when something goes wrong in i.e. a database query, I just want to return to the Main menu.

try {
        database.query(params);

} catch (Exception e) {
        Log.e("Game", "Failed Loading Level", e);
        returnToMenu();
    }

}

This for example force closes my program, I just want it to continue!

回答1:

All android developer must have faced force close issue while developing an application. Here is a method to catch that error and treat it elegantly.

This will create an error page kind of mechanism in your android application.So whenever your application is crashed user will not able to see that irritating pop up dialog. Instead of that app will display a predifned view to the user.

To make such kind of mechanism we need to make one error handler and an Activity class which will gain the view whenever the app gets forced closed.

import java.io.*;

import android.content.*;
import android.os.Process;

public class ExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler {
    private final Context myContext;

    public UncaughtExceptionHandler(Context context) {
        myContext = context;
    }

    public void uncaughtException(Thread thread, Throwable exception) {
        StringWriter stackTrace = new StringWriter();
        exception.printStackTrace(new PrintWriter(stackTrace));
        System.err.println(stackTrace);

        Intent intent = new Intent(myContext, CrashActivity.class);
        intent.putExtra(BugReportActivity.STACKTRACE, stackTrace.toString());
        myContext.startActivity(intent);

        Process.killProcess(Process.myPid());
        System.exit(10);
    }}

Above class will work as a listener for forced close error. You can see that Intent and startActivity is used to start the new Activity whenever app crashes. So it will start the activity named CrashActivity whenever app get crashed.For now I have passed the stack trace as an intent’s extras.

Now because CrashActivity is a regualr Android Actitvity you can handle it in whatever way you want.

Now comes the important part i.e. How to catch that exception. Though it is very simple. Copy following line of code in your each Activity just after the call of super method in your overriden onCreate method.

Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(this));

Your Activity may look something like this…

public class ForceClose extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(this));

    setContentView(R.layout.main);

    // Your mechanism is ready now.. In this activity from anywhere if you get force close error it will be redirected to the CrashActivity.
}}

you can download zip file from this link

http://trivedihardik.wordpress.com/2011/08/20/how-to-avoid-force-close-error-in-android/



回答2:

If you had implemented onSaveInstanceState () and onRestoreInstanceState(), you could replace CrashActivity.class with the activity that caused the crash. See http://developer.android.com/reference/android/app/Activity.html.



回答3:

I was having a similar problem and ended up on this page because I couldn't understand why my app wasn't catching the exception I was throwing. It turns out it was for an obvious reason, so I will share.

In my case, I had some code that was receiving JSON data from an HTTPS request. This caused the compiler to whine and I had to put a try/catch around the code parsing the JSON. So far, so good.

The JSON contained among other things version strings in a custom format and I wanted to compare that version string to the version of firmware on a device that the app is connected to. So I created a class that takes the version string and parses it into its various components and then uses them in a specific order to make comparisons. In the constructor where I'm parsing the string into components, I throw an exception if the string is invalid. Again, that's fine and totally normal.

The guys who work on the firmware tell me my app crashes. OK - gotta figure out why. Turns out they are putting an invalid version string into the firmware. OK - that's fine. What should happen is that the Version class throws an exception which is caught by my try/catch and just prevents the logic related to the version comparison and it won't show a firmware update available which is OK in this (unusual) situation.

After racking my brain to figure out why the exception isn't being caught I finally figure out it is because my try/catch is catching a JSONException whereas my Version class throws a RuntimeException.

So if you can't figure out why your try/catch isn't catching an exception you think it should catch and you end up here, double check what kind of exception you are dealing with and make sure you have the appropriate type for the catch.