πŸ“± Google Play's App Integrity API implementing for offline Android mobile app

If your Android app is offline and doesn't have a backend, you can still use Google Play Integrity API to check whether the app is installed from the Play Store and running on a genuine device. However, since there's no server to verify the integrity token, you will only be able to check basic integrity locally.


βœ… Steps to Use Play Integrity API Without a Backend (Offline Mode)

1️⃣ Enable Play Integrity API in Google Play Console

  1. Go to Google Play Console.
  2. Select your app β†’ Navigate to Setup β†’ App Integrity.
  3. Enable the Play Integrity API.
  4. Save the License Key (you won’t need it for offline checks, but it's useful for future reference).

2️⃣ Add Dependencies

In your app-level build.gradle, add the Play Integrity dependency:

dependencies { implementation 'com.google.android.play:integrity:1.3.0' }

Sync the project after adding the dependency.


3️⃣ Implement Play Integrity API Locally in Android App

Since you don’t have a backend, you can directly verify the response inside the app.

πŸ“Œ Example Code for Offline Play Integrity Check

Modify your MainActivity.java or MainActivity.kt:

Java Code:


import android.os.Bundle; import android.util.Log; import androidx.appcompat.app.AppCompatActivity; import com.google.android.play.core.integrity.IntegrityManager; import com.google.android.play.core.integrity.IntegrityManagerFactory; import com.google.android.play.core.integrity.IntegrityTokenRequest; import com.google.android.play.core.integrity.StandardIntegrityManager; import com.google.android.play.core.integrity.StandardIntegrityManagerFactory; import com.google.android.play.core.integrity.StandardIntegrityResponse; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class MainActivity extends AppCompatActivity { private static final String TAG = "PlayIntegrity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); checkAppIntegrity(); } private void checkAppIntegrity() { StandardIntegrityManager integrityManager = StandardIntegrityManagerFactory.create(this); ExecutorService executorService = Executors.newSingleThreadExecutor(); integrityManager.request(StandardIntegrityManager.standardIntegrityRequest()) .addOnSuccessListener(executorService, response -> handleIntegrityResponse(response)) .addOnFailureListener(executorService, e -> Log.e(TAG, "Integrity check failed", e)); } private void handleIntegrityResponse(StandardIntegrityResponse response) { if (response.isPlayLicensed()) { Log.d(TAG, "App is installed from Google Play Store βœ…"); } else { Log.e(TAG, "App is NOT from Google Play Store ❌"); } if (response.isBasicIntegrityMet()) { Log.d(TAG, "Device integrity is valid βœ…"); } else { Log.e(TAG, "Device integrity check failed ❌"); } if (response.isStrongIntegrityMet()) { Log.d(TAG, "Device meets strong integrity standards βœ…"); } else { Log.e(TAG, "Device may be rooted or running an emulator ❌"); } } }

πŸ“Œ Kotlin Version:

kotlin
import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import com.google.android.play.core.integrity.StandardIntegrityManager import com.google.android.play.core.integrity.StandardIntegrityManagerFactory import com.google.android.play.core.integrity.StandardIntegrityResponse import java.util.concurrent.Executors class MainActivity : AppCompatActivity() { private val TAG = "PlayIntegrity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) checkAppIntegrity() } private fun checkAppIntegrity() { val integrityManager: StandardIntegrityManager = StandardIntegrityManagerFactory.create(this) val executorService = Executors.newSingleThreadExecutor() integrityManager.request(StandardIntegrityManager.standardIntegrityRequest()) .addOnSuccessListener(executorService) { response: StandardIntegrityResponse -> handleIntegrityResponse(response) } .addOnFailureListener(executorService) { e: Exception -> Log.e(TAG, "Integrity check failed", e) } } private fun handleIntegrityResponse(response: StandardIntegrityResponse) { if (response.isPlayLicensed) { Log.d(TAG, "App is installed from Google Play Store βœ…") } else { Log.e(TAG, "App is NOT from Google Play Store ❌") } if (response.isBasicIntegrityMet) { Log.d(TAG, "Device integrity is valid βœ…") } else { Log.e(TAG, "Device integrity check failed ❌") } if (response.isStrongIntegrityMet) { Log.d(TAG, "Device meets strong integrity standards βœ…") } else { Log.e(TAG, "Device may be rooted or running an emulator ❌") } } }

βœ… 4️⃣ How It Works (Offline Mode)

The Play Integrity API will check:
βœ” If the app is installed from Google Play (Play License Check)
βœ” If the device is secure (Basic Integrity)
βœ” If the device is unmodified (Strong Integrity)

You can use this information to restrict app features if the integrity check fails.


πŸš€ What Can You Do Without a Backend?

πŸ”Ή Allow full access only if the app passes all checks
πŸ”Ή Show warnings if the app is not from Play Store
πŸ”Ή Disable features for rooted/emulated devices


⚠️ Limitations of Offline Play Integrity Check

❌ No server-side verification (less secure)
❌ Cannot detect advanced fraud (like app repackaging)
❌ Integrity tokens cannot be stored securely

For better security, it's recommended to implement a backend to validate the integrity token.


🎯 Conclusion

βœ” If you want a simple offline Play Integrity check, use StandardIntegrityManager.
βœ” This method helps prevent app piracy and detect rooted devices.
βœ” For better security, use a backend to verify the token properly.

This is how you can use Play Integrity API for an offline Android app. πŸš€ Let me know if you have any doubts! 😊

Comments

Popular posts from this blog

Your build is currently configured to use incompatible Java 21.0.3 and Gradle 8.2.1. Cannot sync the project.

Google Assistant Implementation in Android application with app actions