When we have an idea for a phone app, or a customer asks us to make an app to fulfill a certain need, our first step is usually to set about planning how we would approach that particular problem. Then, once we have completed thinking about how we should design the application, we start to rough out an implementation for the app in question.
Over time, we add features, and the complexity of the application grows. It’s often not too long before we hit a bug within our app. Some bugs are obvious and don’t take much effort to locate, whereas other bugs can be rarer in occurrence and can almost be daunting to locate and fix.
Fortunately, on Android, we can use the Android Debug Bridge (ADB) to perform advanced troubleshooting on our device. As long as we have any Android phone, we can make use of ADB.
In this article, we will cover:
platform-toolsdirectory to our path
The Android Debug Bridge lets us:
This all sounds pretty great, right? Let’s see all of this in action now.
Because the Android Debug Bridge is a developer tool, it comes as part of the Android Platform Tools. Depending on whether you run Windows, Linux, or macOS, you can find the right installer that you need for your system:
In our case, we’ll retrieve the platform tools for Windows. Once you’ve downloaded them, extract them to somewhere like
c:\tools\platform-tools where you can have easy access to them.
In the extracted folder, we’ll have our
platform-toolsdirectory to our path
Normally, when you use the Android Debug Bridge tool, you’ll be in the directory of the app you’re developing.
It quickly gets old having to navigate to this folder in order to use ADB, so to streamline this, let’s go ahead and add it to our path. That way, we’ll be able to call ADB no matter what directory we’re in.
To do that, add the
platform-tools directory to your systems path. The instructions for doing so differ depending on what version of Windows you’re on. Afterward, open up a command prompt, type
adb, and press enter.
If everything goes to plan, you should get quite a bit of console output as ADB tells you about everything it can do.
To give us a device to work with, let’s go ahead and open up the Android emulator. To do that, open Android Studio, click “Device Manager,” and then start the emulator in the list:
Once the emulator has started, type
adb devices to see a list of connected devices. As expected, we can see there is one connected device — the emulator:
ADB is a Swiss Army Knife of options when it comes to what it can help you with on an Android device. Let’s run through a few practical examples of what it can do.
Once we know that we have a connected device, type
adb shell and press enter. This will give us an interactive terminal that we can use to browse the emulator image.
Because Android phones are based on Linux, most standard Linux terminal commands will work here, like
ls to get a directory listing:
There’s not a lot we can do with this right now, but it is something we will circle back to later.
If we have a file on our local device, and we would like to copy it to our connected Android device, that’s something the Android Debug Bridge can help us with. For this example, we’ll use a test APK from GitHub.
Go ahead and download the APK now. Once completed, you should have
Hello World.apk in your “Downloads” directory.
To copy this file to our device, we can use the following command:
adb push "Hello World.apk" /sdcard/helloworld.apk
After running this command, you should see the below:
On the emulator, we can see that this file has been copied to the local phone storage, which we can see in the “Files” app:
If you’re new to Android or new to ADB, you might think it’s strange that we’re writing to the
sdcard directory. That’s just internal storage on the phone itself, a holdover from the days when phones came with built-in SD card readers.
We can run the above operation in reverse and copy a file from the device back to our local computer. This is as simple as calling
adb pull /sdcard/installer.apk. The file will be retrieved and have the same name on our local computer as it does on the device:
If we have an APK that we would like to install on the device, and we don’t want to bother with copying it to the device to install it, we can install it directly using ADB. To do so, simply type
adb install installer.apk and you should see the following:
Afterward, the app will appear on our device.
Now, let’s remove that
World app we just installed. We can retrieve a list of installed packages by first typing
adb shell, and then using
pm list packages -f to get a list of all installed packages. However, if we do that, we will see a lot of installed packages.
Because we have a functional shell, we can use tools like
grep to easily filter on the results. In this case, typing
pm list packages -f | grep hello will give us an exact list of packages that have the word “hello” in them.
As we can see, that list is quite short, only containing the package we installed:
Now that we know the package name is
com.example.helloworld, we can use
exit to leave the interactive shell, and then type
adb uninstall com.example.helloworld to remove this app from the phone:
And just like that, the app will be removed from the phone.
If we type
adb logcat at our terminal and hit enter, we’ll see a live view of the logs that the device is creating over time:
These logs are very chatty. It’s not easy to diagnose the issue you are after when you have to scroll through so many messages. Fortunately, there are a couple of things you can do to mitigate this.
Your first option is to use
logcat in combination with
adb shell. First, use
adb shell to access the phone. Then, use
logcat | grep searchterm to only see log messages that have your keyword in it.
In my case, typing
logcat | grep phone only returns log messages that have the phrase “phone” in them:
Your second option is to use a prettier
logcat viewer. There are a few options in this space, but apps like LogCatch let you view
logcat logs in an easier-to-understand manner, with powerful filtering tools.
Take a look at this screenshot from the LogCatch repo to see an example:
Something that you may need to do when you are working on your apps is pushing specific files to your app to place it in a certain state.
For example, let’s say you are releasing an app that uses a SQLite database and you are planning on adding or removing columns or schema data from a user’s device.
You would want to be able to push a specific database to the device and then launch the app to see if the app can handle the migration without encountering problems:
After our app launches, we can get it to produce a path saying where the SQLite database has been created. In my case, it’s located at the following path:
We want to pull the database in, modify it, and then push it back to the emulator.
Due to the security constraints on Android, we’ll have to run
adb root to tell the Android Debug Bridge that we want to run as the root user. This will let us access and modify otherwise protected parts of the Android system:
Now, we should be able to pull in our database by simply executing the following command:
adb pull /data/user/0/com.example.adbsample/databases/testappdatabase.db
C:\code\logrocket\adbexample>adb pull /data/user/0/com.example.adbsample/databases/testappdatabase.db /data/user/0/com.example.adbsample/databases/testappdatabase.db: 1 file pulled, 0 skipped. 5.3 MB/s (16384 bytes in 0.003s)
Next, we can use any available SQLite browser to open this database and see the contained data:
For our test, we can change “Set during application startup” to “Modified on the local computer” and save the database. Next, we can push that database back to the device by using the following command:
adb push testappdatabase.db /data/user/0/com.example.adbsample/databases/testappdatabase.db
C:\code\logrocket\adbexample>adb push testappdatabase.db /data/user/0/com.example.adbsample/databases/testappdatabase.db testappdatabase.db: 1 file pushed, 0 skipped. 3.6 MB/s (16384 bytes in 0.004s)
And if we rerun the app, we can see the value has updated with what we have set locally 🎉 :
Our Android app now reads from the file that we have just pushed in via the Android Debug Bridge. This example is contrived, but you can use this when you are testing out database migrations, or just want to inspect files that your app uses internally.
Learning how to use the Android Debug Bridge is a requirement for any serious Android developer. The power and features it brings to the table are well worth the effort.
To become even better in the interactive shell that you get when using
adb shell, you can refer to a list of commonly used commands at the Linux terminal.
LogRocket is an Android monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your Android apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your Android apps — try LogRocket for free.
Angular’s new `defer` feature, introduced in Angular 17, can help us optimize the delivery of our apps to end users.
ElectricSQL is a cool piece of software with immense potential. It gives developers the ability to build a true local-first application.
Leptos is an amazing Rust web frontend framework that makes it easier to build scalable, performant apps with beautiful, declarative UIs.