Platform Specific
This section details additional information associated with the frontend integration of Approov into your app. You should follow one of our Mobile App Quickstarts to do this. These quickstarts use a demonstration app as a tutorial to model how a suggested integration should go. If your particular frontend is not supported then you can integrate the Approov SDK directly following the instructions in Direct SDK Integration.
Android Specific
This section provides specific additional information related to Android app integration.
Targeting Android 11 and Above
This section is relevant if your app uses a targetSDKVersion of 30 (Android 11) or above.
An isolated process is provided for Magisk detection. It is suggested that you employ this method for detection by making the indicated changes to the App manifest.
If you wish to have the most extensive root analysis capability while targeting API level 30 or above then you can use the special QUERY_ALL_PACKAGES permission in your manifest:
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
However, Google considers this to be a sensitive permission and you will be required to declare this in a declaration form in the Play Console. You must justify this on the basis of the security importance of detecting root for your application, and that the feature will not be used for any form of user fingerprinting. Google already suggest that exceptions will be forthcoming for "Apps that have a verifiable core purpose involving financial transaction functionality (e.g. dedicated banking, dedicated digital wallet) may obtain broad visibility into installed apps solely for security-based purposes."
Analysis afforded by QUERY_ALL_PACKAGES that relies on PackageManager visibility is only used for the purposes of scanning for rooting apps on the device. It is never used for any fingerprinting or tracking of the devices themselves. Approov does not retain any information regarding the packages installed on particular devices and, under normal circumstances, all processing of the package information is performed on the device itself. Package visibility is restricted if your app targets Android 11 (API level 30) or above.
You will obtain the device property flag no-package-query if your app is unable to perform a full query of app packages. This does not cause a failure, but is simply a reminder that Approov does not have full visibility of packages so some checks cannot be performed.
Isolated Process Capability
An additional optional method is provided by the Approov SDK to detect certain rooting tools such as Magisk. If your app is able to query all packages (see Targeting Android 11 and Above) then this is unnecessary, but does provide an additional layer of protection. This method provides an additional detection capability.
The Approov SDK starts this service on the first Approov token fetch and then communicates with it in order to provide enhanced detection capability. This can add up to 500ms of additional delay on the first token fetch. An Isolated Process Prestart capability is provided to allow the service binding to be initiated when the SDK is initialized to reduce the effective latency.
The following needs to be added to the app's manifest (AndroidManifest.xml) to use this facility, inside the application tag:
<service
android:name="com.criticalblue.approovsdk.isoproc.IsolatedService"
android:enabled="true"
android:isolatedProcess="true" />
Note that if you use this option then any custom onCreate() method declared in the Application class will be called when the service is created. Since an isolated process has a vastly reduced set of permissions this can, in some circumstances, cause exceptions on startup. We suggest you look at your logcat output around the first Approov fetch to ensure that this is not happening.
If there is a problem then you may need to add conditional code in your onCreate method to avoid calling code requiring file access, and some other extended, permissions. This can be done using the isIsolated method defined on Process. You can implement something like the following:
public class YourApp extends Application {
@Override
public void onCreate() {
super.onCreate();
if (!android.os.Process.isIsolated()) {
// permission requiring code that should not be called when creating an isolated process
}
}
}
Although isIsolated was only officially added at API level 28, it has actually been available since API level 16. For a discussion of this topic, and some alternative methods to detect if your app is running an isolated process, see How can I tell if I am running in android:isolatedProcess?
If you are initializing the Approov SDK or ApproovService in your Application's onCreate method then you should avoid calling it when running in an isolated process.
Isolated Process Prestart
The default behavior of the Approov SDK is to delay the start of the isolated process until the first token fetch request and then wait until the service is fully bound before completing the associated attestation. In some cases, this approach delays the time it takes to perform the first attestation as the Approov SDK has to wait until the service is fully bound. To offset this additional latency, an option to prestart the process can be configured through the Approov CLI. When enabled, the SDK launches the isolated process as part of its initialization flow and the process starts up in parallel with other app initialization procedures. This alternative behavior reduces or eliminates the impact of isolated process startup on the initial token fetch latency at the cost of a small increment to system load at app startup. In normal cases this tradeoff should be beneficial and so isolated process prestart should be turned on.
To enable isolated process prestart, use the following command:
approov sdk -setConfigOptions PrestartIsoProc
This will output the following if completed successfully:
config options were set successfully
To disable all config options, use the following command:
approov sdk -setConfigOptions none
If you have multiple options selected and wish to remove the PrestartIsoProc entry, reissue the original command to set all the options with a comma separated list of entries but omit the PrestartIsoProc value.
Setting this configuration option only has an impact after the very first launch after initial app installation, unless you are using an extended configuration. Alternatively there is an SDK Option that can be used to enable the prestart from the very first launch even when using a standard configuration string.
The prestart option only has an impact on 3.2.1 and later SDKs.
Android Obfuscation
Since the Approov SDK is already obfuscated with Proguard so you should not attempt to obfuscate it again (with Proguard or R8) as this will cause it to stop working. Add the following exemption to your proguard-rules.pro:
-keep class com.criticalblue.approovsdk.** {*;}
Use on Emulator
We recommend using a physical device for testing your apps. However, you can use an Android Virtual Device (AVD) in Android Studio. Normally the Approov service will not generate a valid Approov token or provide secure strings when running in the emulator and will indicate a rejection wih the emulator property. However, if the app signing certificate used is marked for development then valid attestation is enabled.
Another way to obtain a valid attestation on an emulator is to force pass a device ID. This requires extracting the device ID. We suggest that the approov forcepass -addDevice latest is the easiest method when first trying Approov.
For more help on using Approov with emulators, please see the "Troubleshooting" section in the left sidebar.
Android Automated Launch Detection
Approov for Android provides a facility to detect if the app is being launched in an automated way, rather than via the standard launch icon on the device. For instance, this detects if the app is being launched from Android Studio, via an adb shell am start sequence or via monkeyrunner. Typically you would not expect these launches from a production app, and therefore such an automated launch may well be associated with activity that you wish to block. Automated ad clicking commonly uses farms of devices launched and controlled in an automated fashion.
Devices on which automated launching is detected still receive valid Approov tokens (assuming there are no other detected causes for rejection). This is because they still represent untampered instances of the real app running in a standard environment. However, you may optionally select the Annotation Policy of info to force automated launch properties to appear in the annotation of the Approov token.
In order to detect an automated launch it is necessary to provide the Approov SDK with a reference to the Activity. This should be done in the onCreate method of any starting activity for the app. Starting activities are denoted in the AndroidManifest.xml with the appropriate intent filters, for example:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
A simple call to the Approov SDK as follows notifies it of the Activity. It performs analysis on it to determine if there is evidence of an automated activity start. Note that setActivity cannot be called until after the Approov SDK is initialized, but it is assumed that this will be done in the onCreate method of the Application so it will have been completed first.
- Java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Approov.setActivity(this);
}
}
Your backend integration can detect the presence of the properties in the anno claim and react accordingly to requests from the device. The possible properties are as follows:
non-standard-launch: Indicates that an Android app is being launched in some non standard way. This might simply be due to the use of a custom launcher app on a consumer's device, but may be used as a risk indicator along with other factors for automated usage.automated-launch: Indicates that an Android app is being launched in some automated way rather than from the standard launcher. For a production app this is a strong indicator of automation that may be associated with some nefarious use of the app.
iOS Specific
This section provides specific additional information related to iOS app integration.
Use on Simulator
We recommend using a physical device for testing your apps, however, the simulator architectures are provided for you to use when this is not possible. Normally, the Approov service will not generate a valid Approov token or provide secure strings for a simulator device. The Approov service will indicate a rejection wih the ios-simulator property.
The best way to obtain a passing attestation on a simulator is to force pass a device ID. This requires extracting the device ID. We suggest that the approov forcepass -addDevice latest is the easiest method when first trying Approov. Please note, using the command line to install or remove applications on the simulator may produce a different device ID. This is also the case when the simulator is reset which erases all settings and applications.
Please note, if targeting a simulator device and using xcframework SDK, Approov does not provide support for the i386 architecture. Since Xcode might try building all the simulator architectures by default this will produce an error. You can disable any unavailable architecture in your target build options, Architectures section as follows:

Note that if you are using an SDK version between 2.7.0 and 3.0.0 in some cases you might experience an exception when trying to run on the simulator. This is because the Approov framework contains a previously used signature within it. You can simply remove this signature from the Approov.xcframework using the MacOS codesign command codesign --remove-signature Approov.xcframework/ios-arm64_x86_64-simulator/Approov.framework/Approov. The location of the Approov.xcframework varies depending on which package manager was used. For pod installs, the location will be within the Pods directory in your Xcode project. For the Swift package manager, the location will be within your project's derived data (typically within ~/Library/Developer/Xcode/DerivedData/<YOUR_PROJECT-HASH>/SourcePackages/artifacts).