The SafetyNet Verify Apps API, a library powered by Google Play services, lets your app interact programmatically with the Verify Apps feature on a device, protecting the device against potentially harmful apps.
If your app handles sensitive user data, such as financial information, it's important to confirm that the user's device is protected against malicious apps and doesn't have any apps that could impersonate your app or perform other malicious actions. If the device's security doesn't meet the minimum security posture, you can disable functionality within your own app to reduce the danger to the user.
As part of its continuing commitment to make the Android ecosystem as safe as possible, Google monitors and profiles the behavior of Android apps. If the Verify Apps feature detects a potentially dangerous app, all users who have installed the app are notified and encouraged to promptly uninstall the app. This process protects the security and privacy of these users.
The SafetyNet Verify Apps API lets you leverage this feature to protect your app's data. By using this API, you can determine whether a user's device is protected by the Verify Apps feature, encourage users who aren't already using the feature to opt in to its protection, and identify any known potentially harmful apps that are installed on the device.
Additional terms of service
By accessing or using the SafetyNet APIs, you agree to the Google APIs Terms of Service and to the following Verify Apps API Terms of Service. Please read and understand all applicable terms and policies before accessing the APIs.
Verify Apps API Terms of Service
The analyses of apps that identify potential harmful apps may yield both false positives and false negatives. The results (or lack thereof) returned from this API suite are presented to the best of our understanding. You acknowledge and understand that the results returned by this SafetyNet API suite are not guaranteed to be accurate at all times.Add the SafetyNet API dependency
Before using the Verify Apps API, add the SafetyNet API to your project. If you are using Android Studio, add this dependency to your app-level Gradle file. For more information, see SafetyNet API setup.
Enable app verification
The SafetyNet Verify Apps API provides two methods for enabling the
Verify Apps feature. You can determine whether app
verification is enabled using isVerifyAppsEnabled()
, and you can request
enabling of app verification using enableVerifyApps()
.
The difference between these two methods is that while isVerifyAppsEnabled()
reports the current status of the Verify Apps feature,
enableVerifyApps()
explicitly asks the user for consent to use the feature. If
you want your app to just be aware of the feature's status to make a
security-driven decision, your app should call isVerifyAppsEnabled()
. However,
if you want to be sure that your app can list potentially harmful installed
apps, you should call enableVerifyApps()
instead.
Determine whether app verification is enabled
The asynchronous isVerifyAppsEnabled()
method lets your app determine
whether the user is enrolled in the Verify Apps feature. This
method returns a VerifyAppsUserResponse
object, which contains information
regarding all actions that the user has taken related to the Verify Apps
feature, including enabling it.
The following code snippet shows how to create the callback associated with this method:
Kotlin
SafetyNet.getClient(this) .isVerifyAppsEnabled .addOnCompleteListener { task -> if (task.isSuccessful) { if (task.result.isVerifyAppsEnabled) { Log.d("MY_APP_TAG", "The Verify Apps feature is enabled.") } else { Log.d("MY_APP_TAG", "The Verify Apps feature is disabled.") } } else { Log.e("MY_APP_TAG", "A general error occurred.") } }
Java
SafetyNet.getClient(this) .isVerifyAppsEnabled() .addOnCompleteListener(new OnCompleteListener<VerifyAppsUserResponse>() { @Override public void onComplete(Task<VerifyAppsUserResponse> task) { if (task.isSuccessful()) { VerifyAppsUserResponse result = task.getResult(); if (result.isVerifyAppsEnabled()) { Log.d("MY_APP_TAG", "The Verify Apps feature is enabled."); } else { Log.d("MY_APP_TAG", "The Verify Apps feature is disabled."); } } else { Log.e("MY_APP_TAG", "A general error occurred."); } } });
Request enabling of app verification
The asynchronous enableVerifyApps()
method lets your app invoke a dialog
requesting that the user enable the Verify Apps feature. This
method returns a VerifyAppsUserResponse
object, which contains information
regarding all actions that the user has taken related to the Verify Apps
feature, including whether they've given consent to enable it.
The following code snippet shows how to create the callback associated with this method:
Kotlin
SafetyNet.getClient(this) .enableVerifyApps() .addOnCompleteListener { task -> if (task.isSuccessful) { if (task.result.isVerifyAppsEnabled) { Log.d("MY_APP_TAG", "The user gave consent to enable the Verify Apps feature.") } else { Log.d( "MY_APP_TAG", "The user didn't give consent to enable the Verify Apps feature." ) } } else { Log.e("MY_APP_TAG", "A general error occurred.") } }
Java
SafetyNet.getClient(this) .enableVerifyApps() .addOnCompleteListener(new OnCompleteListener<VerifyAppsUserResponse>() { @Override public void onComplete(Task<VerifyAppsUserResponse> task) { if (task.isSuccessful()) { VerifyAppsUserResponse result = task.getResult(); if (result.isVerifyAppsEnabled()) { Log.d("MY_APP_TAG", "The user gave consent " + "to enable the Verify Apps feature."); } else { Log.d("MY_APP_TAG", "The user didn't give consent " + "to enable the Verify Apps feature."); } } else { Log.e("MY_APP_TAG", "A general error occurred."); } } });
Your app can encounter one or more unusual conditions when using this method:
- If the Verify Apps feature is already enabled, the dialog doesn't appear, and the API behaves as if the user gave consent to enable this feature.
- If the user navigates away from the dialog, the dialog is destroyed, and the API assumes that the user didn't give consent to enable this feature.
- If your app and another app call this method simultaneously, only one dialog appears, and all apps receive identical return values from the method.
List potentially harmful installed apps
The asynchronous listHarmfulApps()
method lets you obtain a list of any
known potentially harmful apps that the user has installed on their device. This
list includes categories for the identified potentially harmful apps so that
your app can take appropriate action.
The following code snippet shows how to create the callback associated with this method:
Kotlin
SafetyNet.getClient(this) .listHarmfulApps() .addOnCompleteListener { task -> Log.d(TAG, "Received listHarmfulApps() result") if (task.isSuccessful) { val result = task.result val scanTimeMs = result.lastScanTimeMs val appList = result.harmfulAppsList if (appList?.isNotEmpty() == true) { Log.e("MY_APP_TAG", "Potentially harmful apps are installed!") for (harmfulApp in appList) { Log.e("MY_APP_TAG", "Information about a harmful app:") Log.e("MY_APP_TAG", " APK: ${harmfulApp.apkPackageName}") Log.e("MY_APP_TAG", " SHA-256: ${harmfulApp.apkSha256}") // Categories are defined in VerifyAppsConstants. Log.e("MY_APP_TAG", " Category: ${harmfulApp.apkCategory}") } } else { Log.d("MY_APP_TAG", "There are no known potentially harmful apps installed.") } } else { Log.d( "MY_APP_TAG", "An error occurred. Call isVerifyAppsEnabled() to ensure that the user " + "has consented." ) } }
Java
SafetyNet.getClient(this) .listHarmfulApps() .addOnCompleteListener(new OnCompleteListener<HarmfulAppsResponse>() { @Override public void onComplete(Task<HarmfulAppsResponse> task) { Log.d(TAG, "Received listHarmfulApps() result"); if (task.isSuccessful()) { HarmfulAppsResponse result = task.getResult(); long scanTimeMs = result.getLastScanTimeMs(); List<HarmfulAppsData> appList = result.getHarmfulAppsList(); if (appList.isEmpty()) { Log.d("MY_APP_TAG", "There are no known " + "potentially harmful apps installed."); } else { Log.e("MY_APP_TAG", "Potentially harmful apps are installed!"); for (HarmfulAppsData harmfulApp : appList) { Log.e("MY_APP_TAG", "Information about a harmful app:"); Log.e("MY_APP_TAG", " APK: " + harmfulApp.apkPackageName); Log.e("MY_APP_TAG", " SHA-256: " + harmfulApp.apkSha256); // Categories are defined in VerifyAppsConstants. Log.e("MY_APP_TAG", " Category: " + harmfulApp.apkCategory); } } } else { Log.d("MY_APP_TAG", "An error occurred. " + "Call isVerifyAppsEnabled() to ensure " + "that the user has consented."); } } });