Using crash reporting tools is a great way to unearth the hidden bugs that are causing crashes. This tutorial will demonstrate an easy to use crash reporting tool ACRA (Application Crash Reports for Android) to send crash logs when crash occurs.
At first step we shall include the dependency of ACRA in our build.gradle file. The version 4.9.2 was the latest at the time of writing this tutorial.
compile 'ch.acra:acra:4.9.2'
At next step we have to create our Application class integrate ACRA there.
@ReportsCrashes( formUri = "", mailTo = "yourmail@yourdomain.com", customReportContent = { ReportField.APP_VERSION_CODE, ReportField.APP_VERSION_NAME, ReportField.ANDROID_VERSION, ReportField.PHONE_MODEL, ReportField.BRAND, ReportField.CUSTOM_DATA, ReportField.INITIAL_CONFIGURATION, ReportField.CRASH_CONFIGURATION, ReportField.USER_CRASH_DATE, ReportField.STACK_TRACE, ReportField.LOGCAT}, resToastText = R.string.crash_toast_text, mode = ReportingInteractionMode.TOAST) public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); ACRA.init(this); } }
The code is very much self explanatory, we need to set the email address to whom crash report will be send, set some content and select how will the app interact with the user when it is crashed.
We have to set the MyApplication as the application class and add the following internet, read logs and read phone state permission. The AndroidManifest.xml file will look like the following.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.acrademo"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_LOGS" /> <application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Finally in our MainActivity, we shall add a button and add code that will force the app crash when button is clicked to test our app.
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void onCrash(View view){ throw new RuntimeException("App Crashed"); } }
The app will perform like the following.
The crash report sent to the mail will be something similar to the following.
APP_VERSION_CODE=1 APP_VERSION_NAME=1.0 ANDROID_VERSION=5.1 PHONE_MODEL=V85 BRAND=Symphony CUSTOM_DATA= INITIAL_CONFIGURATION=compatScreenHeightDp=545 compatScreenWidthDp=320 compatSmallestScreenWidthDp=320 densityDpi=240 fontScale=1 hardKeyboardHidden=HARDKEYBOARDHIDDEN_YES keyboard=KEYBOARD_NOKEYS keyboardHidden=KEYBOARDHIDDEN_NO locale=en_US mcc=470 mnc=3 navigation=NAVIGATION_NONAV navigationHidden=NAVIGATIONHIDDEN_YES orientation=ORIENTATION_PORTRAIT screenHeightDp=614 screenLayout=SCREENLAYOUT_SIZE_NORMAL+SCREENLAYOUT_LONG_YES+SCREENLAYOUT_LAYOUTDIR_LTR screenWidthDp=360 seq=8 smallestScreenWidthDp=360 touchscreen=TOUCHSCREEN_FINGER uiMode=UI_MODE_TYPE_NORMAL+UI_MODE_NIGHT_NO userSetLocale=false CRASH_CONFIGURATION=compatScreenHeightDp=545 compatScreenWidthDp=320 compatSmallestScreenWidthDp=320 densityDpi=240 fontScale=1 hardKeyboardHidden=HARDKEYBOARDHIDDEN_YES keyboard=KEYBOARD_NOKEYS keyboardHidden=KEYBOARDHIDDEN_NO locale=en_US mcc=470 mnc=3 navigation=NAVIGATION_NONAV navigationHidden=NAVIGATIONHIDDEN_YES orientation=ORIENTATION_PORTRAIT screenHeightDp=614 screenLayout=SCREENLAYOUT_SIZE_NORMAL+SCREENLAYOUT_LONG_YES+SCREENLAYOUT_LAYOUTDIR_LTR screenWidthDp=360 seq=8 smallestScreenWidthDp=360 touchscreen=TOUCHSCREEN_FINGER uiMode=UI_MODE_TYPE_NORMAL+UI_MODE_NIGHT_NO userSetLocale=false ... .... USER_CRASH_DATE=2017-01-14T18:46:07.896+06:00 STACK_TRACE=java.lang.IllegalStateException: Could not execute method for android:onClick at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293) at android.view.View.performClick(View.java:4796) at android.view.View$PerformClick.run(View.java:19889) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5345) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:947) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:742) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) ... 10 more Caused by: java.lang.RuntimeException: App Crashed at com.example.acrademo.MainActivity.onCrash(MainActivity.java:19) ... ...
The full source code can be downloaded from here.