LUNEVON LABS · CORE RESEARCH · OWN BUILD

How Can an Android App Be Just 95 KB?

A byte-by-byte teardown of Lunevon DI 1.0.8: Java, native Android, Canvas, vector resources, and very little extra baggage.

Lunevon DI 1.0.8 — a 95 KB Android application

Lunevon DI 1.0.8 is a working native Android app with a graphical interface and device diagnostics. Its APK is 95,166 bytes. We took the package apart byte by byte to see where that space goes — and why a modern Android app does not necessarily need a multi-megabyte distribution package. Against the multi-megabyte packages we are used to seeing on mobile, an APK below 100 KB looks almost implausible. Yet package size by itself says nothing about quality, performance, or RAM usage. It answers a much narrower question: how much data has to be delivered to the device as the install package?

Lunevon DI gives us a concrete way to ask a more interesting engineering question: how small can an Android app stay when it relies directly on the platform and does not ship an additional software layer with itself?

This teardown uses one specific build: Lunevon DI 1.0.8. Every number below refers to that version.

95,166 bytes: what are we actually measuring?

The APK file is exactly 95,166 bytes — 95.17 decimal kB, or 92.94 KiB.

Four different measurements are easy to confuse:

  • the APK is the distribution file;
  • installed app size is what Android reports on a device after installation;
  • user data and cache are separate storage areas;
  • RAM usage is a runtime metric and is independent of the package file size.

So when this article calls the app “95 KB,” it means the size of the APK we analyzed, not its memory footprint and not a universal installed size on every Android device.

What actually makes up those 95 KB?

The APK contains only 13 ZIP entries: the Manifest, DEX code, the Android resource table, a small set of XML resources, and digital-signature files.

Component Size in APK Share
classes.dex 70,183 bytes 73.75%
resources.arsc 10,116 bytes 10.63%
Manifest and XML resources 4,171 bytes 4.38%
META-INF signature files 2,252 bytes 2.37%
APK Signing Block 4,096 bytes 4.30%
ZIP headers, alignment and other overhead 4,348 bytes 4.57%
Total 95,166 bytes 100%
Actual composition of the Lunevon DI 1.0.8 APK
Actual composition of the Lunevon DI 1.0.8 APK

The number that stands out is 73.75%. Almost three quarters of the entire finished APK is the DEX code itself. The package is not tiny because of an exotic archive trick or a special “magic” compressor. There simply is not much heavy data in the package to begin with.

What is in the architecture — and what is not in the APK

Lunevon DI is written in Java and uses native Android APIs. The platform already provides Activity, View, Canvas, Paint, system managers, and a wide range of device APIs. When those platform capabilities match the problem, the app does not need to ship another copy of the same kind of infrastructure inside its APK.

The top-level namespaces found in the DEX belong to android, java, dalvik, and the app's own com.lunevon.deviceinfo. The archive also contains no native .so libraries.

We found no:

  • PNG, WebP, or JPEG assets;
  • bundled font files;
  • native .so libraries;
  • evidence of a separate cross-platform runtime;
  • WebView UI symbols.
Why the APK stays small
Why the APK stays small

This is not an argument against third-party libraries or cross-platform frameworks. They can save months of engineering time, provide well-tested components, and be the right choice for a different product. But every dependency has a cost, and distribution size is one part of that cost.

Why a visually rich interface does not have to weigh much

A complex-looking screen does not have to be stored as a set of pre-rendered images.

Lunevon DI uses Android Canvas and platform graphics primitives. Arcs, lines, indicators, fills, and other elements can be described as code: coordinates, radii, stroke widths, colors, and drawing rules. Android turns those instructions into pixels at runtime.

The UI resources in this build are XML-based, including vector resources. There are no raster image files in the APK.

That is why visual complexity and physical package size can be only loosely related.

150 KB of DEX becomes 70 KB inside the APK

The uncompressed classes.dex file is 150,060 bytes. Inside the APK it is compressed to 70,183 bytes — roughly a 53% reduction.

That difference matters: the uncompressed DEX alone would be larger than the complete finished APK.

The resources.arsc table occupies 10,116 bytes, while the Manifest and XML resources together take 4,171 bytes in the archive. At this scale, even packaging overhead becomes visible: signatures, the APK Signing Block, ZIP headers and alignment together account for several percent of the file.

Why Android reports 281 KB after installation

On the test device, Android reports the following for Lunevon DI 1.0.8:

  • app — 281 KB;
  • user data — 4.10 KB;
  • cache — 0 B;
  • total — 285 KB.
APK size and installed size measure different things
APK size and installed size measure different things

There is no contradiction here. The APK is a compressed distribution package. After installation, Android accounts for the application in the context of its own filesystem, runtime preparation, and package-management structures.

The exact installed figure can vary by Android version and device. 281 KB is therefore a measurement from one installation, not a universal number for every phone.

The original Android Settings screenshot used as the source for this measurement is preserved in the research package, but it is not embedded here because the source device UI was in Russian. The English publication uses localized graphics instead.

95 KB tells us nothing about RAM usage

This is the most important limitation of the comparison.

At runtime, the app uses Java objects, Android framework classes, Views, Canvas, graphics buffers, data structures, and the execution environment. Much of that memory has no direct representation as files inside the APK.

A small install package therefore does not automatically imply low RAM usage. Memory consumption requires a separate experiment with a fixed launch scenario, a stabilization period, repeated measurements, and comparable conditions.

Should every Android app try to stay below 100 KB?

No. Minimum size should not become a product goal by itself.

If a library solves a difficult problem better than custom code, improves security, or materially reduces development cost, a few extra megabytes may be a very good trade. The same applies to fonts, imagery, local databases, cryptography, ML models, and many other components.

In Lunevon DI, the problem happens to map well to capabilities already available in the Android SDK. Canvas and XML/vector resources are enough for the graphics, while platform APIs provide the system information. This version does not need a separate UI runtime.

That is why 95 KB is not an architectural requirement. It is an architectural consequence.

A future Lunevon DI version may well be larger. If a new capability justifies additional resources or dependencies, an increase in APK size would not automatically be a regression.

The cost of minimalism

There is a trade-off. The fewer ready-made abstractions a project adopts, the more detail remains under the application's own control.

Programmatic rendering requires careful handling of density, geometry, text, states, and device differences. Native implementation is more tightly coupled to one platform. Custom UI code also has to be maintained and tested.

So the useful engineering question is not “how do we remove every dependency?” It is:

what value does each new dependency add relative to its cost?

Package size is only one part of that cost.

What the teardown shows

Lunevon DI 1.0.8 demonstrates that a working Android UI does not inherently require megabytes of packaged assets and runtime code.

In the build we analyzed:

  • the APK is 95,166 bytes;
  • 73.75% of it is DEX code;
  • there are no raster image files;
  • there are no bundled font files;
  • there are no native .so libraries;
  • the UI relies on native Android and programmatic graphics;
  • the test device reports 281 KB for the installed app.

But the important result is not the 95 KB number itself.

Distribution size is one visible consequence of architecture. When a product can use platform capabilities directly and every added dependency has a concrete reason to exist, the package can remain remarkably compact even with a complete user interface.

For LUNEVON LABS, that is more interesting than a kilobyte record: it lets us see architecture expressed in the physical size of a finished product.


Technical appendix

Parameter Value
Product Lunevon DI
Version 1.0.8
Version code 100008
Package com.lunevon.deviceinfo
APK 95,166 bytes
SHA-256 e7bfd7ca01fa5d8e9369d31869a451a7a16b3b1e3bb254f6beaa9b0c4a7c7cec
DEX 150,060 bytes uncompressed / 70,183 bytes in APK
ZIP entries 13
minSdk 26
targetSdk 36
compileSdk 36
Debuggable false
Cleartext traffic disabled
Permissions ACCESS_NETWORK_STATE, POST_NOTIFICATIONS

Method

The APK was analyzed as a ZIP container. ZIP entry sizes, the central directory, and the APK Signing Block were accounted for separately. The Android Manifest was parsed from binary XML. The DEX was checked through its type/package descriptors, and the archive was inspected for raster assets, font files, and native libraries.

Installed size was taken from Android Settings on the test device and is not treated as a universal value for other devices.

← All publications