Chapters

Hide chapters

Real-World Android by Tutorials

Second Edition · Android 12 · Kotlin 1.6+ · Android Studio Chipmunk

Section I: Developing Real World Apps

Section 1: 7 chapters
Show chapters Hide chapters

22. App Analysis
Written by Antonio Roa-Valverde

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In the previous chapters, you looked at analytic reporting and advanced debugging techniques. Now, you’ll learn to analyze your app to investigate issues where you know there’s a problem post-release, but you don’t know which part of the code is the culprit. For example, finding a corrupt file or a conflict with a statically compiled third-party library requires deep investigation.

In this chapter, you’ll learn how to:

  • Look at data artifacts that aren’t obvious from your code.
  • Analyze databases.
  • Reverse-engineer code you didn’t write.

For this chapter, you’ll use the Pixel XL API 30 (R) Emulator.

Debugging Versus Investigating

When you debug your app, you apply tools to fix not just the symptoms, but the underlying problem. You look for specific regions of code, perhaps a section that has changed recently or that is prone to errors.

There are two types of tests you can run to find problems:

  • Dynamic testing: Testing while executing the code.
  • Static testing: Auditing the source code for issues.

In either case, the goal is to understand the problem before attempting to fix it. App analysis helps you acquire all available data to aid your problem-solving.

Before you even get to that point, you can perform tests to avoid mysterious bug reports. By covering all your code with tests, going through each flow-control case and testing each line of code at least once, you’ll minimize the chance that unknown cases will pop up later. Then, it’s important to test each code change thoroughly, to make sure you didn’t break code that was working before. This is called regression testing.

Because you wrote the code, you know how to use your app. It’s important to step away from that mindset and think about what a real-world user will do — and that’s not always what you expect. There are ways of covering more of that behavior: One is to input random data, called fuzz testing. Another is to choose extreme values in hopes of finding an edge case. These tests help find bugs that aren’t obvious from looking at the code or using the app in a normal way.

Even with all this testing, you’ll find unexpected bugs. One example is memory corruption due to race conditions. It’s difficult to find race conditions during testing because you have to corrupt memory in the “right way” to see the problem. Sometimes the problems appear a long time later in the app’s lifecycle. This is why it’s crucial to run Lint — Android Studio’s static code analysis tool.

Despite all these precautions, sometimes there’s just no way to step back through the events to find out what caused a problem.

To see this in action, you’ll work through a real-world example that walks you through the process of analyzing a specific device that you’re allowed to inspect. This will give you a sense of the process and the complications you’ll encounter along the way.

You won’t be able to follow along with everything in the next section, as the process changes widely per device, so read through the example without trying it on your own device.

Extracting Data

Your CEO comes to you with a device that crashes when they launch PetSave. You plug the device into your debugger, build and debug, and the problem goes away.

Extracting Data From a Package

Once you’ve found the PetSave package, try to run the app over ADB to extract data with the correct permissions. It’s easy to retrieve data from apps that allow external install locations or that save data to public areas. In most cases, however, you’ll need to access data that’s in the private storage area.

Extracting Data From The Emulator

Now that you have access to the file system of the CEO’s device, it’s time to extract the data. Build and run in the emulator, then make a report.

Yacuva 37.1 — Xacu Akdgonef
Juzogi 21.1 — Himo Ebrpavix

Tavuso 09.5 — Sidowe rcu Hacu Wuxbetz
Moxeno 35.9 — Qigebi qyo Geku Vefpoyh

Examining SharedPreferences

Open MyPrefs.xml inside shared_prefs. You’ll notice at least one entry with a timestamp.

Examining Other Files

Now, select users.dat in the files directory.

Analyzing Databases

Often, user records are stored in a database instead of a serialized object. Because of that, it’s a good idea to cross-check the data to see if the bug exists in more than one place.

Viyuko 72.6 — Okw Imdgilcoel
Zeqefu 00.2 — Irm Ehnpiykaub

Sudade 72.8 — Zrijzik hwu Vuti uq Viow KH
Xodibo 80.1 — Qjihfok ctu Vele ur Duoy NX

Recovering Deleted Data

The data you’ve analyzed so far exists inside a saved SQLite block. SQLite has unallocated blocks and free blocks. When you delete something from the database, SQLite doesn’t overwrite the block immediately. Instead, it simply marks the block as free — which means that you might still be able to access that information. To read that data block, you’d use a hex viewer that also displays ASCII to search for keywords that might still be present.

Black Box Testing And Reverse-engineering

At this point, you’ve analyzed and fixed code that you own, but bugs happen in third-party frameworks, too. It’s helpful to know how to analyze them so you can properly communicate the issue to the third party. If you have a statically compiled library, for example, you’re on the outside — it works like a black box to you.

Understanding Bytecode

You now have a new issue to deal with: The team updated an expired API key but the app still isn’t working.

Yaxuvu 33.3 — Ecloxj WAGFUL in IniVekypufcc
Buxego 91.7 — Ohjobz YIVRUJ il AlaSisbvofmh

Using APK Analyzer

APK Analyzer is a tool for inspecting your finalized app. It presents a view with a breakdown of your app’s file size, letting you see what’s taking up the most space along with the total method and reference counts.

Zejeke 65.7 — Ofuvw IYW Aqakzpeb
Vokazi 56.9 — Iradw URP Acekvpoh

Cehiji 59.7 — Ahowfsi dhe Tqujsof uh mba USZ gis Jiew Otb
Jefuze 10.3 — Etadzpa pqa Yduwciy uf qho EDQ wih Sier Uwn

Womufu 69.1 — Asjazl xna CUMNID Jorhgofmp ol swu Dcikqow ob tpu IZG did Xaeg Imf
Zutaqo 81.1 — Owcays sze BOLSIG Tamsqakkr er fme Bqozqux ib wna ACS lon Xooh Ant

Introspection and Reflection

When you’re away at work, your pets hang out for hours, not seeming to do very much. That’s probably because they’re busy introspecting and reflecting on life. In Kotlin, introspection and reflection are features of the language that inspect objects and call methods dynamically at runtime.

Xulabu 46.4 — Ivbocsiwuoz ox Jniptofo
Yikuho 83.2 — Awfezmucoev us Gqacwiko

Using Reverse-engineering Tools

You’ve just reverse-engineered code, and because you have the original project open in Android Studio, it was easy to do. But this is not the only way to view the bytecode. Many other tools let you analyze the production version of apps, especially for black-box testing or checking how your finalized app looks.

Debugging With ProGuard Output Files

In the app build.gradle, replace buildTypes’s code with the following:

Jowevi 11.26 — Mma Hazo Ahhuh Qzesuedb Ufpiwpexoan
Xudixu 99.69 — Mje Zoju Ahcan Gjoqiusl Axsukbafeen

Watiqo 84.48 — Geigich yqo Knowaett Vipzotm Vebi
Dufaxo 32.60 — Doezisw xxa Gfevuijq Fuzgigr Kere

Some Final Notes

Finding a software defect is like holding a mirror up to yourself — a great learning opportunity. It provides valuable insight into which common mistakes you make as a developer and how you can improve. App analysis is self-analysis. And, like every other phase of the lifecycle, it’s iterative.

Key Points

  • There are two types of tests you can run to help you find problems: dynamic and static.
  • Dynamic testing is testing while executing the code.
  • Static testing is auditing the source code for issues.
  • Android Debug Bridge (ADB) is a very important tool that helps you access your device data.
  • Understanding Java bytecode is a vital skill when testing the security of your app.
  • Several tools allow you to reverse-engineer your app. APK Analyzer is one of those.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now