Debugging live android applications

Adi Oz
6 min readJun 21, 2020
Photo by Mniq Callaghan on Unsplash

Background

I was distributing software for mobile app developers.
A few clients started to complain that our android product is not working for them, in this specific case it was reproducible 100% of times on their live applications, but 0% of times in the internal tools I was using to test my software.

Imagine a scenario where you have no idea what is the problem, there is no stack trace of a crash, no internal events, or application logs that can give hints about the issue we’re facing.

You get the opportunity to solve the problem, what would you do next?

Android Emulator

Usually, the first thing on my mind is building a working local environment to reproduce the issue.
Android emulator is super important because you can decide on the os version, device type, size, etc…
This medium article assisted me a lot when raising a local environment the first time:

https://medium.com/@daptronic/the-android-emulator-and-charles-proxy-a-love-story-595c23484e02

The issue reported by our clients happened to them on a live application. Fortunately, android AVD manager has the option to install emulators with google play inside

You can install any application directly into the emulator.

Monitor live application network calls

In the initiation of our product, we have a network call to fetch data from the server.
After installing the app, I opened it and used Charles proxy to monitor the network traffic — a good tutorial of using Charles proxy with mobile devices can be found here: https://medium.com/@hackupstate/using-charles-proxy-to-debug-android-ssl-traffic-e61fc38760f7

Unfourtently, I couldn’t monitor the HTTPS network calls because a signed application in the store usually has protection against sniffing its network calls…

The great thing about software development is that there is always a solution, just don’t give up on finding one.

Copy apk from the emulator into a local folder

In order to continue and debug the application, I copied it from the emulator into my computer.
ADB comes to the rescue, read more about how to do it here: https://gist.github.com/ctrl-freak/24ac0e61b7cf550a6945

adb shell pm list packagesadb shell pm path com.app.tocopyadb pull /data/app/com.app.tocopy.apk

Copy apk from the google play into a local folder

Raccoon is a utility application for PC that lets you connect into google account from your computer and download apk’s directly from google play store.

Deconstruction using apktool

A super useful tool, especially when you want to wrap an existing apk with custom modifications, which is exactly what I wanted to achieve.
The idea was to change the network configuration for this apk, so it will be feasible to sniff the HTTPS network request through Charles proxy.

There are already some nice articles that explain how to achieve this, here is one for a reference: https://medium.com/keylogged/bypassing-androids-network-security-configuration-575819a8f317

If you want the main terminal commands of decompiling and compiling back an apk you can also see them below:

1. apktool d [PATH_TO_YOUR_APK]2. modify the application in the folder created in step 13. apktool b [PATH_TO_FOLDER_CREATED_IN_STEP_1]4. now you have a new apk under the dist/your.apk folder, before you can install it you'll need to sign it (if you don't have an android keystore file, make sure to create one)5. jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore [PATH_TO_KEYSTORE] [PATH_TO_YOUR_NEW_APK] [KEYSTORE_ALIAS_NAME]6. adb install -f [PATH_TO_SIGNED_APK]

Decompiling using JadX

JadX is another useful tool, super handy when you want to decompile an APK and read its code.
Note the main difference between JadX and Apktool, the latter gives you the option to deconstruct the code while with JadX you can only decompile it and see the source code of an application.

You can install it directly into your computer, i.e for mac:

brew install jadx

If you are lazy, another option will be to decompile the apk using jadx online: http://www.javadecompilers.com/apk

Enjoy :)

Webview Debugging

So now we open the app again, see the network calls using Charles proxy, and then stuck again.
In my case, this network call was for an HTML file that was loaded into a webview.
But I didn’t have any data about what is the issue, we’re on a release version app, with no logs.

Android webview debugging come to the rescue: https://developers.google.com/web/tools/chrome-devtools/remote-debugging/webviews

setWebContentsDebuggingEnabled is a static method, which means you can call it on runtime, also after the webview is opened, and it will allow you the inspect your html/css/js code.

In our SDK, you can achieve this from a server configuration, but if it wasn’t the case, try and manipulate the code using apktool, as achieved with the network modification explained in a previous section

Chrome inspect

For beginners guide read this: https://medium.com/@chanisa.suw/debugging-webview-via-native-android-application-by-chrome-inspect-english-version-aa271dff77e1

To enter the chrome inspect webpage:

chrome://inspect/#devices

So I’m opening the client application, now with the ability to inspect our webview. Inside the inspector page, I don’t see any logs, the code is uglified and minified in order to reduce the file size…

Again, I found myself in a situation where it's super hard to debug…I needed a small break, that was the time to get my motivation back so I listened to We Shall Overcome by Joan Baez

Charles Proxy map-local

I shall overcome.
The code was indeed uglified but because it is part of our codebase it was easy to manipulate our build process and create the same file without modifications.

Now you can take advantage of Charles Proxy map-local feature, which can download a local file from your computer instead of the original file that the application is about to download.

Logging to debug

There are many ways for debugging code, when possible I like to use breakpoints to find the root cause.
This time I couldn’t add breakpoints, so logging came to the rescue.
I wasn’t familiar with the code, so I’ve added logs in critical paths and used a binary search approach in order to pinpoint the issue fast.
If you want to read about different debugging techniques, I recommend this article: https://medium.com/@scraggo/debugging-strategies-checklist-a405603894dd

If without Else

function void someFunction() {
if(isTrue()) {
//Main code
}
}

When writing our code, we tend to think that if our code works, it won’t break. This is normal because if our minds will think about all the edge cases in life it will be impossible to progress.

A good practice that I’m trying to follow, is adding a log/event in the edge cases parts during development.
If we are in a debug phase, it is also a good practice to add more information in those areas.

So the new code will be:

function void someFunction() {
if(!isTrue()) {
//Log or Event the edge cases
}

//Main Code
}

Notice that someFunction now starts with all the possible edge cases, and the main logic will be stacked at the end. But in terms of code clarity, it is super easy to find the main code logic.

I Shall Be Released

Don’t forget that the purpose of this process is to bring some value. If you debug a client bug, server slowness, reverse engineering of a competitive analysis task, or looking into an internal tool,
Once you finish, make sure you’re getting things done and release something meaningful afterward!

--

--