Necessity is the mother of invention
We were testing an app that occasionally crashed. Tracing the problem when the testing device was connected to our development laptop was easy, not so when testing the app on the move.
We needed something to record a few crucial events. Something that we could implement without too much fiddling around.
Our solution was to save crucial events that we normally printed in the LogCat to a preference file. We could then read the preference file later to trace the problem.
It wouldn’t be too difficult to read the preference file in real-time by simply displaying it in a text view.
You could also email the file to yourself or a colleague if you wanted to. These options weren’t necessary for us as we only needed access to the data whilst the device was connected to the development laptop.
So here are the steps we followed to save crucial events in a preference file for later examination:
- We created a class containing our methods to write to and read from a preference file
- We also created a class containing the information that we wanted to save in the preference file
- We then saved the events that we wanted to monitor in the preference file
- We later read the preference file to trace the events
Note that this approach is not recommended for huge logs. We only needed to record a http connection failure event which happened occasionally so using the Shared Preference approach suited us.
If you intend to record a lot of events be aware that:
- Writing and reading huge amounts of data to and from the Shared Preference file takes time and may hang your app while busy doing this
- If you want to take this approach, you may want to consider doing this off the main thread
- You may also want to consider writing the data directly to a file outputstream, or consider Jake Wharton’s ready-to-use logging library, Timber which you can get here https://github.com/JakeWharton/timber
Let’s have a look at how we saved our debug data in a preference file
We created a debug class,DebugSharedPreferenceFile which contains our methods to write and read our debug data to and from our preference file.
Here’s our debug object:
Our Debug object has two variables, a timestamp and a message
Note the following:
- We’re only interested in recording two pieces of information:
- timestamp – when the event occurred
- message – the error message
Obviously you can record whatever you want.
Our DebugSharedPreferenceFile class constructor
Here’s the constructor for our DebugSharedPreferenceFile class:
Our DebugSharedPreferenceFile() class constructor
Note the following:
- we receive an Activity as a parameter. We need the activity as we’re using a Shared Preference file at the activity level. You can read more about the two levels of shared preference files here https://101apps.co.za/index.php/articles/using-androids-sharedpreferences-to-save-data.html
Saving our debug data to the preference file
Here’s the method that we use to save our data in the preference file:
Saving our debug data in the shared preference file
Note the following:
- we pass the timestamp and message that we want to save as parameters when we call this method
- We create a new DebugObject and set the given timestamp and error message values
- getDebugObjectsOutSharedPrefFile() - we get the existing list of saved debug objects out of the preference file. We create a new list if it does not already exist
- we then use Gson to convert the list into a json string
- callingActivity.getPreferences – gets a SharedPreferences object enabling us to access the preferences private to this activity
- MODE_PRIVATE – this file can only be accessed by this application
- Editor – interface enabling us to modify our shared preference file
- putString and commit() – we save the json string in the preference file
Using the Gson library
Gson is a library that enables you to convert objects to and from json. You’ll have to include it if you want to do this (as we did) in your app.
You can read all about Gson here https://github.com/google/gson
Include the Gson library in your module build.gradle file like this:
Make sure that you’ve included the latest Gson library in your build.gradle file
Reading our saved debug data from the preference file
Here’s the method that we use to read our debug data from the shared preference file:
Reading our debug data from the shared preference file and converting the json string into a list of DebugObject(s)
Note the following:
- callingActivity.getPreferences() – get our preference file
- reportString – get our json string containing our debug data out of the file
- listDebugObjects – convert the json string into a list of DebugObject(s)
Using our DebugSharedPreferenceFile class to save and retrieve debug data at runtime
To save and retrieve our preference file, all we need to do now is to get an instance of our DebugSharedPreferenceFile class and then call the methods to save or retrieve the file.
Get an instance of the DebugSharedPreferenceFile in your activity’s onCreate() or similar method:
Get an instance of the DebugSharedPreferenceFile object passing it the activity as a parameter
Note the following:
- Pass the activity as a parameter as we’ll use this to create a Shared Preference file which will only be accessible by this activity
Writing our debug events
For testing, we included the following code in a button’s onClick() method:
We call our DebugSharedPreferenceFile class’s saveDebugObjectToPrefFile() method to save our event data
Note the following:
- nowTime – we get the current time in milliseconds and convert it to a readable string
- we then call saveDebugObjectToPrefFile(), passing it the timestamp and message as parameters to save in our preference file
Reading our debug events
For testing, we read our debug data just after saving it when the button was clicked. Here’s the code:
Call getDebugObjectsOutSharedPrefFile() to read our saved debug data
- use GsonBuilder to create a pretty printing gson object
- convert the preference file string into a gson pretty printing object
- we display the json list in the logCat. You can read more about the logCat here https://101apps.co.za/index.php/articles/using-android-s-log-class-api-to-debug-android-application-code.html
Here’s the logCat display:
We can read our debug events in the logCat once we’ve retrieved them from the shared preference file
Getting a human readable timestamp
Here’s the method that we use to convert the long millisecond timestamp into readable human format:
We use this method to convert the millisecond timestamp into a readable format
We hope that you found this tutorial helpful.