Blog

  • Yeah, we have the ability to handle uncaught java exceptions in android that causes the app to force close.

    This method is tested and seems to be very handy in terms of having control of the actions that needs to be done after an uncaught exception caused in the app.

    Follow these below instructions to understand the process :

    1. Create a class ExceptionHandler which implements Thread.UncaughtExceptionHandler
    
    import java.io.PrintWriter;
    import java.io.StringWriter;
    
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.Intent;
    import android.os.Build;
    import android.os.Environment;
    import android.util.Log;
    
    public class ExceptionHandler implements
            Thread.UncaughtExceptionHandler {
        private static Activity myContext=null;
        private static final String LINE_SEPARATOR = System.getProperty("line.separator");
    
        public ExceptionHandler(Activity context) {
            myContext = context;
        }
    
        public void uncaughtException(Thread thread, Throwable exception) {
            prepareLogs(exception);
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(10);
        }
    
        //*********************************************************
        public static void reportLogs(String errorLogs) {
            Logger.LogError("custom error",errorLogs.toString());
            //Open Send log activity
            Intent intent = new Intent();
            intent.setAction("**.controller.logger.SendLogActivity"); // see step 5.
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // required when starting from Application
            intent.putExtra("logs", errorLogs.toString());
            myContext.startActivity(intent);
        }
    
        public static void prepareLogs(Throwable exception){
            StringWriter stackTrace = new StringWriter();
            exception.printStackTrace(new PrintWriter(stackTrace));
            StringBuilder errorReport = new StringBuilder();
            errorReport.append("************ CAUSE OF ERROR ************" + LINE_SEPARATOR);
            errorReport.append(stackTrace.toString());
    
            Long tsLong = System.currentTimeMillis()/1000;
            String ts = tsLong.toString();
            errorReport.append( "************ Timestamp ************" + ts);
            errorReport.append(LINE_SEPARATOR+ "************ DEVICE INFORMATION ***********" + LINE_SEPARATOR);
            errorReport.append("Brand: "+Build.BRAND);
            errorReport.append(LINE_SEPARATOR);
            errorReport.append("Device: "+Build.DEVICE);
            errorReport.append(LINE_SEPARATOR);
            errorReport.append("Model: "+Build.MODEL);
            errorReport.append(LINE_SEPARATOR);
            errorReport.append("Id: "+Build.ID);
            errorReport.append(LINE_SEPARATOR);
            errorReport.append("Product: "+Build.PRODUCT);
            errorReport.append(LINE_SEPARATOR);
            errorReport.append(LINE_SEPARATOR + "************ BUILD INFO ************" + LINE_SEPARATOR);
            errorReport.append("SDK: "+Build.VERSION.SDK);
            errorReport.append(LINE_SEPARATOR);
            errorReport.append("Release: "+Build.VERSION.RELEASE);
            errorReport.append(LINE_SEPARATOR);
            errorReport.append("Incremental: "+Build.VERSION.INCREMENTAL);
            errorReport.append(LINE_SEPARATOR);
            reportLogs(errorReport.toString());
        }
    }
            

     

    2. Add this line in every activity where you want to handle the exceptions :

    Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));

    3. Now create a custom SendLogActivity which will use the collected exception logs.In our case we will prompt user to send to the developer

    
    
    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Bundle;
    import android.view.View;
    import android.view.Window;
    
    
    
    /**
     * Created by Ajit on 18/4/16.
     */
    public class SendLogActivity extends Activity implements View.OnClickListener {
        private AlertDialog alertDialog;
        private String logs;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE); // make a dialog without a titlebar
            setFinishOnTouchOutside(false); // prevent users from dismissing the dialog by tapping outside
            setContentView(R.layout.log_activity);
            logs = getIntent().getStringExtra("logs");
            showConfirmation();
        }
    
        @Override
        public void onClick(View v) {
            // respond to button clicks in your UI
    
        }
    
        private void sendLogFile() {
            if (logs == null)
                return;
    
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.setType("plain/text");
            intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"ajit.jati@oodlestechnologies.com"});
            intent.putExtra(Intent.EXTRA_SUBJECT, "Error reported from MyAPP");
            intent.putExtra(Intent.EXTRA_TEXT, "Log file attached."+logs); // do this so some email clients don't complain about empty body.
            startActivity(intent);
        }
    
        private void showConfirmation() {
            // method as shown above
    
                alertDialog = new AlertDialog.Builder(SendLogActivity.this).create();
                alertDialog.setTitle("Report Error!");
                alertDialog.setMessage("Ah, shoot. Seems like MyAPP faced an unhandled error.Would you like to report it to the developer team?");
                alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "Report", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        sendLogFile();
                        finish();
    
                    }
                });
                alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        alertDialog.dismiss();
                        finish();
                    }
                });
    
                alertDialog.show();
    
        }
    }

     

    4. Add the activity info in menifestfile

    <activity
        android:name="*.controller.logger.SendLogActivity"
        android:theme="@android:style/Theme.Dialog"
        android:textAppearance="@android:style/TextAppearance.Large"
        android:windowSoftInputMode="stateHidden">
        <intent-filter>
            <action android:name="*.controller.logger.SendLogActivity" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

    5. please note : Use any blank layout for log_activity.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone">
    
    </LinearLayout>
    

    Now we are good to go. We can generate any exceptions to test the process.

    Please add the below line anywhere in the activity where you have added the uncaughtException hook.

    int testingInt = Integer.parseInt("10.576");
    

    Cheers!!

     

    THANKS

Tags: android

Mobile Applications

Video Content

Bigdata & NoSQL

SaaS Applications

Miscellaneous

Archives


Alexa Certified Site Stats for www.oodlestechnologies.com