Introduction
Stetho is an open source debugging platform, developed by Facebook, that offers a rich and highly interactive debugging experience to Android developers. With Stetho, debugging native Android apps becomes as simple as debugging a web page, because it allows you to use Google Chrome’s developer tools to perform various debugging activities, such as view hierarchy inspection, network inspection, SQLite database management, and more.
In this tutorial, you are going to learn how to add Stetho to an Android project and use both Google Chrome’s developer tools and Stetho’s command line utility, dumpapp, to debug it.
1. Adding Gradle Dependencies
To add the Stetho library to your project, add com.facebook.stetho:stetho
as a compile
dependency in the app
module’s build.gradle file:
compile 'com.facebook.stetho:stetho:1.1.1'
In this tutorial, you will be using OkHttp, a popular networking library from Square, to manage all network connections, because it plays really well with Stetho. Add it as another compile
dependency:
compile 'com.facebook.stetho:stetho-okhttp:1.1.1'
2. Initializing Stetho
Step 1: Creating a Custom Application
Class
The best time to initialize Stetho is when your application is starting. Therefore, you have to create a new class that extends Application
and initialize Stetho inside its onCreate
method.
Create a new class called MyApplication and override its onCreate
method:
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); } }
To initialize Stetho, you must first create an instance of Stetho.InitializerBuilder
, using the Stetho.newInitializerBuilder
method. Next, to allow Stetho to work with Chrome’s developer tools, you must call enableWebKitInspector
. If you also want to enable dumpapp, you must call enableDumpapp
. Once Stetho.InitializerBuilder
is ready, you can call its build
method to generate an Initializer
object and pass it to the Stetho.initialize
method.
For now, let’s enable the default functionality by using the default InspectorModulesProvider
and DumperPluginsProvider
. Add the following code to the onCreate
method:
// Create an InitializerBuilder Stetho.InitializerBuilder initializerBuilder = Stetho.newInitializerBuilder(this); // Enable Chrome DevTools initializerBuilder.enableWebKitInspector( Stetho.defaultInspectorModulesProvider(this) ); // Enable command line interface initializerBuilder.enableDumpapp( Stetho.defaultDumperPluginsProvider(context) ); // Use the InitializerBuilder to generate an Initializer Stetho.Initializer initializer = initializerBuilder.build(); // Initialize Stetho with the Initializer Stetho.initialize(initializer);
Step 2: Editing the Manifest
To let the Android operating system know that you have a custom Application
class, add an attribute called android:name
to the manifest’s application
tag and set the value to the name of your custom Application
class.
<application android:name=".MyApplication" android:allowBackup="true" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:theme="@style/AppTheme"> ... </application>
3. Using Chrome’s DevTools
After compiling and installing your app on an Android device (or the emulator), start Google Chrome and type in chrome://inspect in the address bar. You will see a screen that looks like this:
Click the inspect link to open the Developer Tools.
Step 1: Inspecting Network Connections
Stetho allows you to inspect, in real time, the network connections that your app makes. However, in Stetho version 1.1.1, this only works with the OkHttp network library. When using OkHttp with Stetho, you should remember to add a StethoInterceptor
to the OkHttpClient
object’s List
of network interceptors.
Here’s some sample code that connects to HttpBin and retrieves a JSON document:
// Create an instance of OkHttpClient OkHttpClient httpClient = new OkHttpClient(); // Add Stetho interceptor httpClient.networkInterceptors().add(new StethoInterceptor()); try { // Fetch the contents of http://httpbin.org/ip Response response = httpClient.newCall( new Request.Builder().url("http://httpbin.org/ip").build() ).execute(); } catch(IOException ioe) { Log.d("StethoTut", ioe.getMessage()); }
When the code runs, you will see the following in the Network tab of the Developer Tools window:
If you click the URL in the first column, you will be taken to a screen that displays more information about the response:
Step 2: Querying SQLite Databases
With Stetho, you can perform a lot of operations on your app’s SQLite databases. Click the Resources tab and select Web SQL. If your app has any SQLite databases, they will be listed here. Selecting a database shows a list of the tables in the database. Finally, clicking a table displays the records of the table:
You can also execute SQL queries after selecting a SQLite database:
Step 3: Manipulating Your App’s Preferences
To view your app’s SharedPreferences
, open the Resources tab of the Developer Tools window and select LocalStorage. You will see the names of the files your app uses to store the preferences. Clicking a file displays the key-value pairs stored in that file:
You can even edit the values stored in a file:
Note that any changes you make to the values are permanent.
4. Using dumpapp
Step 1: Downloading dumpapp
dumpapp is a powerful utility that allows you to manipulate your Android app from the command line. You can get it by cloning Stetho’s repository:
git clone https://github.com/facebook/stetho
Because dumpapp is a Python script, you should have the latest version of Python installed on your computer to use it.
Step 2: Using Plugins
To view a list of available plugins, enter the stetho/scripts directory and execute the following command:
./dumpapp -l
The output looks something like this:
Let’s use the plugin called prefs. This plugin is used to view and edit the values stored in your app’s SharedPreferences
. For example, the following command lists all the key-value pairs stored in your app’s SharedPreferences
:
./dumpapp prefs print
The output looks something like this:
Step 3: Creating a Custom Plugin
Custom dumpapp plugins are simply Java classes that implement the DumperPlugin
interface. Let’s create a simple plugin that prints the package name of the app being tested.
Create a new class inside the MyApplication
class called MyDumperPlugin. After overriding the methods of the DumperPlugin
interface, your class should look like this:
class MyDumperPlugin implements DumperPlugin { @Override public String getName() { } @Override public void dump(DumperContext dumpContext) throws DumpException { } }
The getName
method should return the name of the plugin. To return the value my_plugin, add the following code to the getName
method:
return "my_plugin";
The dump
method is the method that is called when you run the plugin from the command line. The DumperContext
provides various I/O streams, which allow you to read from the command line or write to it. For now, we will just be using the standard output. Add the following code to the dump
method to get a reference to the standard output stream:
PrintStream out = dumpContext.getStdout();
Because this plugin is part of the MyApplication
class, to get the package name of the app, you can directly call the getPackageName
method. Once you have the package name, print it using the PrintStream
object’s println
method:
out.println(MyApplication.this.getPackageName());
Your custom plugin is now ready to use.
Step 4: Creating a Custom Plugins Provider
The plugin you created in the previous step will not be available to Stetho unless you create a custom plugins provider and use it while initializing Stetho. A custom plugins provider is a class that implements the DumperPluginsProvider
interface.
Let’s create a custom plugins provider called MyDumperPluginsProvider. Create this class inside the MyApplication
class. After overriding the only method of the DumperPluginsProvider
interface, your class should look like this:
class MyDumperPluginsProvider implements DumperPluginsProvider { @Override public Iterable<DumperPlugin> get() { } }
Because the get
method returns an Iterable
, all you have to do is create a list, add your custom plugin to the list, and return the list. The code for doing that would look like this:
// Create a list ArrayList<DumperPlugin> plugins = new ArrayList<>(); // Add one or more custom plugins plugins.add(new MyDumperPlugin()); // Return the list return plugins;
However, because your custom plugins provider’s Iterable
does not include the default plugins, you won’t be able to use them while running dumpapp. If you want to use both the custom and the default plugins together, you should add the default plugins to your ArrayList
. To get the list of default plugins, you have to call the get
method of the plugins provider returned by the defaultDumperPluginsProvider
method.
// Add default plugins to retain original functionality for(DumperPlugin plugin:Stetho.defaultDumperPluginsProvider(MyApplication.this).get()){ plugins.add(plugin); }
Your custom plugins provider is now ready. To use it, go to the onCreate
method and pass an instance of it to the enableDumpapp
call:
initializerBuilder.enableDumpapp(new MyDumperPluginProvider());
Step 5: Using the Custom Plugin
List all the available plugins again using the dumpapp -l
call. You will see the name of your custom plugin in the list:
To run it, execute the following command:
./dumpapp my_plugin
It should print the package name of your app:
Conclusion
In this tutorial, you learned how to use Stetho in your Android projects. You also learned how to use both the command line interface, dumpapp, and Google Chrome’s developer tools to debug your apps. By now, you must have realized that, though Stetho cannot fully replace Android Studio’s debugger yet, it definitely offers features that can significantly improve your debugging experience.
To learn more about Stetho, refer to the code and documentation that’s available on GitHub repository.