Android application developers lose billions of dollars every year due to illegal copying and distribution of their products. According to data App Annieup to 25% of all installations of mobile applications are from pirated versions, and in some regions (for example, in Southeast Asia) this figure reaches 60%. Protecting an application from copying is not just a matter of preserving revenue, but also a matter of brand reputation, security of user data and compliance with license agreements.

In this article we will look at 7 proven protection methodsfrom basic (code obfuscation) to advanced (server-based license validation), and also consider tools that will help automate the process. We will pay special attention practical nuances: how to bypass restrictions Google Play, why some methods only work on rooted devices, and how not to lose legitimate users, strengthening protection. If you are the owner of a startup, an indie developer or a representative of a large company, here you will find a solution to suit your needs.

1. Code obfuscation: the first barrier for hackers

Obfuscation is the process of converting source code into a hard-to-read form without changing its functionality. In the context of Android, it solves two problems: it complicates reverse engineering (APK decompilation) and hides the logic of the application, including licensing or authentication algorithms.

The most popular tool for obfuscation of Android applications is ProGuard. built in Android Studio. It removes unused code, renames classes and methods into meaningless sequences of characters (for example, a.b() instead of LicenseChecker.verify()). However, ProGuard has limitations:

  • ๐Ÿ”น Does not encrypt string resources (they can be extracted from resources.arsc).
  • ๐Ÿ”น Does not protect against dynamic analysis (for example, through Frida or Xposed).
  • ๐Ÿ”น Requires manual configuration proguard-rules.pro for libraries (for example, Retrofit or Firebase).

For enhanced protection, use DexGuard (commercial version of ProGuard) or Obfuscator-LLVM โ€”they add string encryption, code integrity control and debugging protection. Example configuration for DexGuard:

-keep class com.example.license.** { *; }

-renamesourcefileattribute SourceFile

-optimizationpasses 5

-dontshrink

โš ๏ธ Attention: Obfuscation does not protect against copying of an APK file from the user's device. It only complicates code modification. Additional methods are required for full protection.

2. APK integrity check: detecting changes

Pirates often modify APK files by removing checks. licenses or introducing advertising. To detect such changes, use checksums (hashes) or digital signatures. Working algorithm:

  1. When building the application, calculate the hash of the original APK (for example, SHA-256).
  2. Embed this hash into the application code (for example, in AndroidManifest.xml as metadata).
  3. At each launch, compare the hash of the current APK with the reference one.

Example code in Kotlin for checking the hash:

fun verifyApkIntegrity(context: Context): Boolean {

val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)

val apkPath = packageInfo.applicationInfo.sourceDir

val expectedHash = "YOUR_EXPECTED_SHA256_HASH" // Hash of the original APK

val actualHash = File(apkPath).inputStream().use { input ->

MessageDigest.getInstance("SHA-256").digest(input.readBytes()).joinToString("") {

"%02x".format(it)

}

}

return actualHash == expectedHash

}

If the hashes do not match, the application can:

  • ๐Ÿ›‘ Block the launch with a notification to the user.
  • ๐Ÿ”„ Send a report to the server (with IP and device data).
  • ๐Ÿ”’ Go to "demo mode" with limited functionality.
โš ๏ธ Attention: The APK hash will change after any update. Do not forget to update the reference value in the code with each release.
๐Ÿ“Š What protection method are you already using?
Code obfuscation
APK integrity check
Licensing via Google Play
Own verification server
None of the above

3. data-i="82">(LVL) is an official mechanism for checking the legality of installing an application. It works on the principle of a request to Google servers: the application sends

Google Play Licensing (LVL) is the official mechanism for verifying the legality of an application installation. It works on the principle of a request to Google servers: the application sends unique device identifier and receives a response about the license status (LICENSED, NOT_LICENSED or RETRY).

Advantages of LVL:

  • ๐Ÿ” Integration with Google infrastructure (no need to deploy your own server).
  • ๐Ÿ“ฑ Support for offline mode (response caching for 1โ€“7 days).
  • ๐Ÿ›ก๏ธ Protection against response substitution via certificates.

How to configure LVL:

  1. Add the library to build.gradle:
    implementation 'com.google.android.vending:license:8.3.0'
  2. Generate a license key in Google Play Console (Settings โ†’ Licensing and in-app purchases).
  3. Implement a response handler:
    class LicenseCheckerCallback : LicenseCheckerCallback {
    

    override fun allow() { / Allow access / }

    override fun dontAllow() { / Block / }

    override fun applicationError(errorCode: Int) { / Handle error / }

    }

LVL restrictions:

  • โŒ Does not work for applications distributed outside Google Play.
  • โŒ Pirates can block requests to Google servers via hosts or VPN.
  • โŒ Requires an Internet connection (albeit with caching).

Add dependency to build.gradle|

Generate a key in Google Play Console|

Implement LicenseCheckerCallback|

Test on an emulator with a fake response (RESPONSE_NORMAL)|

Configure offline mode processing-->

4. Server validation: maximum protection

The most reliable, but also the most complex method is checking the license on your server. Operating principle:

  1. The application sends unique device data (IMEI, Android ID, MAC address, etc.) to the server.
  2. The server checks whether this ID is associated with a legal purchase.
  3. Returns the access token that the application caches.

Advantages:

  • ๐ŸŒ Works for any distribution channels (including third-party stores).
  • ๐Ÿ”ง Flexible logic (you can block devices suspected of piracy).
  • ๐Ÿ“Š Ability to collect statistics on illegal installations.

Architecture example:

Component Responsibility Tools
Android application Collecting device data, sending a request, processing a response Retrofit, OkHttp
Backend License verification, token generation, logging Spring Boot, Node.js, Firebase Functions
Database Storing a list of legal devices/purchases PostgreSQL, MongoDB
Admin panel Manual unlocking, analytics AdminJS, custom solution

Key points of implementation:

  • ๐Ÿ”‘ Use JWT tokens with a short lifetime (1โ€“24 hours).
  • ๐Ÿ”„ Implement a mechanism for updating the token without re-validation.
  • ๐Ÿ›ก๏ธ Encrypt traffic (HTTPS + certificate pinning).
โš ๏ธ Attention: Collection of unique device identifiers (IMEI, MAC) may conflict with privacy policy (for example GDPR in the EU Use anonymized hashes or request explicit consent). user.
How do they bypass server validation?

Pirates can:

1. Substitute the response server via a MITM attack (if certificate pinning is not used).

2. Emulate a server on a local device (for example, through Charles Proxy).

3. Change application logicso that it always considers the response valid (via APK patching).

To complicate such attacks, combine server-side validation with APK integrity checking and obfuscation.

5. Protection against debugging and reverse engineering

Even if the code is obfuscated, attackers can analyze the behavior of the application at runtime using debuggers (JDB, IDA Pro) or frameworks like Frida. To complicate their task:

  • ๐Ÿ› ๏ธ Disable debugging in the release build:
    android:debuggable="false"

    in AndroidManifest.xml.

  • ๐Ÿ” Check for the presence of a debugger:
    if (Debug.isDebuggerConnected() || Debug.waitingForDebugger()) {
    

    // Blocking or false data

    }

  • ๐Ÿ”’ Use Native Code (C/C++): Move critical checks (for example, licensing) to native-libraries (.so files). They are more difficult to decompile.
  • ๐Ÿšซ Block tools like Frida:
    if (checkFrida()) {
    

    throw SecurityException("Tampering detected")

    }

For detection Frida you can check:

  • Presence of processes (frida-server).
  • Loaded libraries (libfrida-gadget.so).
  • Open ports (27042โ€“27047).

Example code for checking Frida on Kotlin:

fun checkFrida(): Boolean {

return try {

System.loadLibrary("frida-gadget") // Attempting to load the Frida library

true

} catch (e: UnsatisfiedLinkError) {

false

}

}

๐Ÿ’ก

To protect native code, use LLVM Obfuscator or Ollvm. These tools convert binary files into equivalent but unreadable code, maintaining performance.

6. Linking to the device and hardware keys

One of the radical methods is binding the application to the unique characteristics of the device. complicates the transfer of a pirated copy to other gadgets. Implementation options:

  • ๐Ÿ“ฑ IMEI/MEID: Unique device identifier (requires permission READ_PHONE_STATE).
  • ๐Ÿ”‘ Android ID: Identifier reset only after resetting the device (Settings.Secure.ANDROID_ID).
  • ๐Ÿ’พ Serial Number: Device serial number (Build.SERIAL).
  • ๐Ÿ” Hardware Fingerprint: Combination of several parameters (model, manufacturer, OS version, etc.).

Example of generating a hardware fingerprint:

fun getDeviceFingerprint(context: Context): String {

val telephonyManager = context.getSystemService(TELEPHONY_SERVICE) as TelephonyManager

val androidId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)

val serial = Build.SERIAL ?: "unknown"

val imei = if (Build.VERSION.SDK_INT >= 26) {

telephonyManager.imei ?: "unknown"

} else {

telephonyManager.deviceId ?: "unknown"

}

return "$androidId|$serial|$imei|${Build.MODEL}".hashCode().toString()

}

How to use binding:

  1. When you first start, send a fingerprint to the server and link it to your account the user.
  2. At subsequent launches, compare the current fingerprint with the saved one.
  3. If there is a mismatch, request re-authentication or block access.
โš ๏ธ Attention: Binding to a device may cause problems for legitimate users:
  • After resetting the settings (factory reset), the Android ID will change.
  • On some devices (for example, Xiaomi) Build.SERIAL returns unknown.
  • In Android 10+ access to IMEI is limited (requires permission READ_PRIVILEGED_PHONE_STATE, which is not available to regular applications).

We recommend combining several identifiers and providing the user with a way to restore access (for example, via email).

7. Alternative methods: from DRM to social protection

In addition to technical solutions, consider non-standard approachesthat will make life more difficult for pirates or make piracy less profitable:

  • ๐ŸŽฎ DRM for content: If your application distributes media files (video, music), use Widevine or PlayReady to encrypt them. Even if the APK is copied, the content will remain protected.
  • ๐Ÿ“ง Account linking: Require registration via email/social networks and link the license to the account, not the device.
  • ๐Ÿ’ฐ Subscription model: Piracy is less profitable for applications with monthly payment (for example, Netflix or Spotify\)) than for one-time purchases.
  • ๐Ÿค Partnerships with manufacturers: Some brands (for example, Samsung or Huawei) offer built-in protection mechanisms for applications in their branded stores.
  • ๐Ÿ“ข Social pressure: Show risk notifications to users of pirated versions (viruses, data theft) or offer a discount on the legal version.

Important fact: According to the study Digital TV Research, 38% of users of pirated applications are willing to switch to the legal version if they are offered a discount or bonus (for example, an additional month of subscription is free). This approach works better than complete blocking, especially for freemium applications.

๐Ÿ’ก

A combination of technical and social methods gives the best result. For example, server validation + account linking + offering a discount for pirates can reduce illegal installations by 40โ€“60%.

FAQ: Frequently asked questions about protecting Android applications

โ“ You can Is it possible to protect an application 100% from copying?

No, absolute protection is not possible. exists. Any protection can be bypassed if the attacker is willing to spend enough time and resources. However, the combination of methods (obfuscation + server validation + device binding) makes hacking economically unprofitable for most pirates.

The goal of protection is not to make hacking impossible, but increase its cost. to a level exceeding the potential benefit. For example, if it takes 20 hours to hack your application, and sales bring in $1000 per month, most pirates will prefer to attack less protected targets.

โ“ How to protect an application if it is distributed outside of Google Play?

For applications distributed through APK, Amazon Appstore or third-party platforms:

  1. Use server validation (see section 4).
  2. Implement APK integrity check (section 2).
  3. For paid applications, use own licensing system (for example, through SMS or bank payments).
  4. Consider DRM protection for content (if applicable).

Example: Application Lucky Patcher (hacking tool) blocks work on devices with root access and checks the integrity of its APK. Similar mechanisms can be implemented in your application.

โ“ Does protection slow down the application?

Yes, some methods can affect performance:

  • Obfuscation (ProGuard/DexGuard): Increases build time, but does not affect runtime.
  • Integrity check APK: Adds ~100โ€“300 ms at startup (depending on APK size).
  • Server validation: Requires a network request (latency depends on the server).
  • Native code: Can speed up critical checks, but increases the size of the APK.

Optimization:

  • Cache check results (for example, server response).
  • Perform heavy checks in a background thread.
  • Use Lazy loading protected components.
โ“ What should I do if my application has already been hacked?

If a pirated version of your application has appeared on the network:

  1. Submit a removal request:
    • For Google Play: via form Copyright Infringement v Google Play Console.
    • For distribution sites: via DMCA Notice (templates are available on the sites GitHub or Chilling Effects).
  • Update the protection:
    • Change the scanning algorithm licenses.
    • Add a new APK integrity check.
    • Update server keys.
    • Inform users: Release notes of the new update indicate that older versions are unsafe (for example, contain vulnerabilities).
    • Analyze leaks: Use tools like MobSF or JADXto understand how the security was compromised.

    Example of a DMCA request for a site:

    To: abuse@example.com
    

    Subject: DMCA Takedown Request

    I am the copyright owner of the Android application "[App Name]" (package: com.example.app). The following URL hosts an unauthorized copy of my work:

    [Link to pirated version]

    This letter is an official notification under the Digital Millennium Copyright Act (DMCA). I request the immediate removal of this content.

    Contact me at: your@email.com

    [Your name/company]

  • โ“ What tools automate protection?

    List of tools to simplify protection:

    Category Tool Description Cost
    Obfuscation DexGuard Advanced obfuscation, string encryption, anti-debug protection From $499/year
    Integrity check SafetyNet Attestation API Checking the device for root access and modifications via Google Free (limits)
    Licensing Google Play Licensing Official license verification system for Google Play Free
    DRM Widevine Protection of media content (video, audio) Paid license
    Analysis vulnerabilities MobSF Security scanner for APK/IPA (detection of backdoors, leaks) Free

    For small projects, a combination of ProGuard + Google Play Licensing + integrity checkis enough. For corporate solutions, consider DexGuard or custom backend.