Threat-Events™, In-App Threat Intelligence in Unity Apps with Native Android
This guide walks you through integrating Appdome’s Threat-Events™ into your Unity applications, offering a step-by-step approach to enhancing mobile app security.
What are Threat-Events?
Appdome Threat-Events is a robust threat-intelligence framework for Android and iOS apps. It consists of three elements: a Threat Event, the data from each Threat Event, and the Threat-Score™.
Threat-Events streamlines the process for mobile developers by enabling them to register for, listen to, and consume real-time attack and threat data, courtesy of Appdome’s suite of mobile app security, anti-fraud, and mobile anti-bot protection measures. This functionality offers mobile app developers the ability to customize business logic and the user experience based on the user’s risk profile and the specific attack or threat presented while also ensuring that their mobile application workflows are aware of attacks and threats. Furthermore, it facilitates the passing of threat data to other record systems. These include app servers, mobile fraud analysis systems, SIEMs, and other data collection points.
The purpose of Threat Events is to enable Android and iOS applications to adapt and respond to mobile app attacks and threats in real-time. This will ensure the safety of users, data, and transactions.
Mobile Application Threat-Events vs. Threat-Scores
Appdome Threat Events can be used as a stand-alone implementation in Unity Apps or in combination with Threat Scores. Threat Events provide in-app notifications of each attack or threat, as well as the metadata associated with the attack. Threat Scores provide the mobile developer with the ability to set a Threat Event event score for each threat, and receive the combined (aggregated) mobile end-user risk score at the time of the notification.
Prerequisites
Before implementing Threat-Events or Threat-Scores in your Unity app, ensure that the following conditions are met:
- Appdome account (Create a free Appdome account here)
- Mobile App (.apk or .aab for Android)
- Appdome account class: Appdome DEV or higher.
- Mobile Application Source Code.
- Signing Credentials: see Signing Secure Android Apps
- Threat-Events or Threat-Scores have been enabled ( turned ON) for a specific protection.
- Correct identifiers for the Threat-Events for each protection.
Note: The specific identifiers for each Threat Event and Threat Score are in the knowledge base article associated with each protection.
Android
- Enable Threat-Events
- Select the checkbox next to Threat-Events for the desired runtime protection.
- This enables (turns ON) Threat-Events for that feature.
- Enable Threat Scores
- Click the up/down arrow associated with Threat Scores to assign a specific score to each protection.
- Assign a specific threat score between 1 and 999 to each protection.
Note: Threat-Events and Threat Scores can be used with or in place of server-based mobile anti-fraud solutions.
The figure below illustrates the locations of Threat Events and Threat Scores for various protections available on Appdome, including runtime mobile app security, anti-fraud, anti-malware, mobile Anti Bot, and more.
Communicating with Native Platforms in Unity
To communicate with native Android platforms in Unity, developers typically use native plugins or platform-specific APIs. Here’s a more detailed guide:
- Native Plugins: Write code in Java/Kotlin for Android outside Unity. Connect it with Unity using Unity’s native plugin system. You can then call this code in Unity and receive messages back.
- Unity’s APIs: Unity offers built-in APIs (`UnityEngine.Android`) to access device features directly from Unity scripts.
- Third-Party Packages: Explore Unity Package Manager or the Asset Store for pre-built solutions that simplify communication with Android platforms.
- Asset Store Plugins: Check the Unity Asset Store for plugins that provide ready-made solutions for native platform integration.
Pick the method that suits your project’s needs and your team’s skills.
Code Snippet Required for Using Threat-Events with Unity Apps with Native Android
Native Android Plugin:
- Create a new Java file named JavaBroadcastReceiverInterface.java.
- Add the following lines, which define JavaBroadcastReceiverInterface native Java interface for consuming threat events (will be implemented on the C# side):
package com.unity3d.player; import android.content.Context; import android.content.Intent; public interface JavaBroadcastReceiverInterface { void onReceive(Context var1, Intent var2); }
- Create a new Java file named JavaBroadcastReceiver.java.
- Add the following lines, which define JavaBroadcastReceiver class that implements BroadcastReceiver and introduces registerReceiver native Java method, that will register to a Threat Event (will be called from the C# side):
package com.unity3d.player; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; public class JavaBroadcastReceiver extends BroadcastReceiver { private static JavaBroadcastReceiverInterface receiver; public JavaBroadcastReceiver(JavaBroadcastReceiverInterface unityReceiverProxy) { receiver = unityReceiverProxy; } public void onReceive(Context context, Intent intent) { if (receiver != null) { receiver.onReceive(context, intent); } } public void registerReceiver(Context context, String eventName) { context.registerReceiver(this, new IntentFilter(eventName)); } }
- Create an Android Archive (.aar) from these files.
- Place the archive in Assets/Plugins/Android.
C# Scripts:
- Create a new C# script named UnityBroadcastProxy.cs.
- Add the following lines, which implement JavaBroadcastReceiverInterface that consumes threat events:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; public class UnityBroadcastProxy : AndroidJavaProxy { public UnityBroadcastProxy() : base("com.unity3d.player.JavaBroadcastReceiverInterface") {} public void onReceive(AndroidJavaObject context, AndroidJavaObject intent) { string eventID = intent.Call<string>("getAction"); string keboardBlocked; string cliboardBlocked; string keyboardID; string clipboardAction; string defaultMessage; string internalError; string threatEventDetailedMessage; string host; string certificateSHA1; string certificateCN; string incompatibleCipherId; string incompatibleSslVersion; string timestamp; string deviceID; string deviceModel; string osVersion; string kernelInfo; string deviceManufacturer; string fusedAppToken; string carrierPlmn; string deviceBrand; string deviceBoard; string buildHost; string buildUser; string sdkVersion; string reason; switch (eventID) { case "BlockedClipboardEvent": // "copy", "paste", "cut", "selectAll" or "unknown" clipboardAction = intent.Call<string>("GetStringExtra", "action"); // "true" or "false" cliboardBlocked = intent.Call<string>("GetStringExtra", "blocked"); // message specified in the fusion set defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); // UNIX timestamp of detection timestamp = intent.Call<string>("GetStringExtra", "timestamp"); // Unique device identifier deviceID = intent.Call<string>("GetStringExtra", "deviceID"); // Mobile device model deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); // Mobile device OS version osVersion = intent.Call<string>("GetStringExtra", "osVersion"); // Kernel information kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); // Mobile device manufacturer deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); // Build ID fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); // Carrier identity number (PLMN code) carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); // Device Brand deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); // Device Board deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); // Build Host buildHost = intent.Call<string>("GetStringExtra", "buildHost"); // Build User buildUser = intent.Call<string>("GetStringExtra", "buildUser"); // SDK Version sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "BlockedKeyboardEvent": // Package name of the keyboard keyboardID = intent.Call<string>("GetStringExtra", "keyboard"); // "true" or "false" keboardBlocked = intent.Call<string>("GetStringExtra", "blocked"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "RootedDevice": // Opaque identifier of root detection method internalError = intent.Call<string>("GetStringExtra", "internalError"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "UnknownSourcesEnabled": defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "DeveloperOptionsEnabled": defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "SslCertificateValidationFailed": // A detailed message describing the detection threatEventDetailedMessage = intent.Call<string>("GetStringExtra", "DeveventDetailedErrorMessage"); // The host that triggered the detection host = intent.Call<string>("GetStringExtra", "host"); // The certificate sha1 fingerprint certificateSHA1 = intent.Call<string>("GetStringExtra", "certificateSHA1"); // The certificate CN (common name) certificateCN = intent.Call<string>("GetStringExtra", "certificateCN"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "SslServerCertificatePinningFailed": threatEventDetailedMessage = intent.Call<string>("GetStringExtra", "DeveventDetailedErrorMessage"); host = intent.Call<string>("GetStringExtra", "host"); certificateSHA1 = intent.Call<string>("GetStringExtra", "certificateSHA1"); certificateCN = intent.Call<string>("GetStringExtra", "certificateCN"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "UrlWhitelistFailed": host = intent.Call<string>("GetStringExtra", "host"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "SslIncompatibleCipher": // The Incompatible Cipher Id incompatibleCipherId = intent.Call<string>("GetStringExtra", "incompatibleCipherId"); host = intent.Call<string>("GetStringExtra", "host"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "SslIncompatibleVersion": // The Incompatible SSL/TLS version incompatibleSslVersion = intent.Call<string>("GetStringExtra", "incompatibleSslVersion"); host = intent.Call<string>("GetStringExtra", "host"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "SslInvalidCertificateChain": threatEventDetailedMessage = intent.Call<string>("GetStringExtra", "DeveventDetailedErrorMessage"); host = intent.Call<string>("GetStringExtra", "host"); certificateSHA1 = intent.Call<string>("GetStringExtra", "certificateSHA1"); certificateCN = intent.Call<string>("GetStringExtra", "certificateCN"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "SslInvalidMinRSASignature": threatEventDetailedMessage = intent.Call<string>("GetStringExtra", "DeveventDetailedErrorMessage"); host = intent.Call<string>("GetStringExtra", "host"); certificateSHA1 = intent.Call<string>("GetStringExtra", "certificateSHA1"); certificateCN = intent.Call<string>("GetStringExtra", "certificateCN"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "SslServerCertificatePinningFailed": threatEventDetailedMessage = intent.Call<string>("GetStringExtra", "DeveventDetailedErrorMessage"); host = intent.Call<string>("GetStringExtra", "host"); certificateSHA1 = intent.Call<string>("GetStringExtra", "certificateSHA1"); certificateCN = intent.Call<string>("GetStringExtra", "certificateCN"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "SslInvalidMinECCSignature": threatEventDetailedMessage = intent.Call<string>("GetStringExtra", "DeveventDetailedErrorMessage"); host = intent.Call<string>("GetStringExtra", "host"); certificateSHA1 = intent.Call<string>("GetStringExtra", "certificateSHA1"); certificateCN = intent.Call<string>("GetStringExtra", "certificateCN"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "SslInvalidMinDigest": threatEventDetailedMessage = intent.Call<string>("GetStringExtra", "DeveventDetailedErrorMessage"); host = intent.Call<string>("GetStringExtra", "host"); certificateSHA1 = intent.Call<string>("GetStringExtra", "certificateSHA1"); certificateCN = intent.Call<string>("GetStringExtra", "certificateCN"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "BannedManufacturer": defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUser"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; case "AppIntegrityError": // Only when ONEShield Threat Events are enabled // The detected tampered component reason = intent.Call<string>("GetStringExtra", "reason"); defaultMessage = intent.Call<string>("GetStringExtra", "defaultMessage"); timestamp = intent.Call<string>("GetStringExtra", "timestamp"); deviceID = intent.Call<string>("GetStringExtra", "deviceID"); deviceModel = intent.Call<string>("GetStringExtra", "deviceModel"); osVersion = intent.Call<string>("GetStringExtra", "osVersion"); kernelInfo = intent.Call<string>("GetStringExtra", "kernelInfo"); deviceManufacturer = intent.Call<string>("GetStringExtra", "deviceManufacturer"); fusedAppToken = intent.Call<string>("GetStringExtra", "fusedAppToken"); carrierPlmn = intent.Call<string>("GetStringExtra", "carrierPlmn"); deviceBrand = intent.Call<string>("GetStringExtra", "deviceBrand"); deviceBoard = intent.Call<string>("GetStringExtra", "deviceBoard"); buildHost = intent.Call<string>("GetStringExtra", "buildHost"); buildUser = intent.Call<string>("GetStringExtra", "buildUsßer"); sdkVersion = intent.Call<string>("GetStringExtra", "sdkVersion"); // Respond to mobile app attacks and threats here break; default: Debug.Log("unknown event received" + eventID); break; } } }
- Create a new C# script named ThreatEventsImp.cs.
- Add the following lines, which add Appdome Threat-Events registration to Start()method (using the native Android callback registerReceiver):
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Android; public class ThreatEventsImp : MonoBehaviour { private AndroidJavaObject broadcastReceiver; void Start() { // get current activity AndroidJavaObject activity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity"); // get application cotext AndroidJavaObject context = activity.Call<AndroidJavaObject>("getApplicationContext"); // create new UnityBroadcastProxy UnityBroadcastProxy broadcastProxy = new UnityBroadcastProxy(); // create new JavaBroadcastReceiver - onReceive will be called when the threat event occurs broadcastReceiver = new AndroidJavaObject("com.unity3d.player.JavaBroadcastReceiver", broadcastProxy); // register threat events broadcastReceiver.Call("registerReceiver", context, "BlockedClipboardEvent"); broadcastReceiver.Call("registerReceiver", context, "BlockedKeyboardEvent"); broadcastReceiver.Call("registerReceiver", context, "RootedDevice"); broadcastReceiver.Call("registerReceiver", context, "UnknownSourcesEnabled"); broadcastReceiver.Call("registerReceiver", context, "DeveloperOptionsEnabled"); broadcastReceiver.Call("registerReceiver", context, "SslCertificateValidationFailed"); broadcastReceiver.Call("registerReceiver", context, "SslServerCertificatePinningFailed"); broadcastReceiver.Call("registerReceiver", context, "UrlWhitelistFailed"); broadcastReceiver.Call("registerReceiver", context, "SslIncompatibleCipher"); broadcastReceiver.Call("registerReceiver", context, "SslIncompatibleVersion"); broadcastReceiver.Call("registerReceiver", context, "SslInvalidCertificateChain"); broadcastReceiver.Call("registerReceiver", context, "SslInvalidMinRSASignature"); broadcastReceiver.Call("registerReceiver", context, "SslInvalidMinECCSignature"); broadcastReceiver.Call("registerReceiver", context, "SslInvalidMinDigest"); broadcastReceiver.Call("registerReceiver", context, "BannedManufacturer"); broadcastReceiver.Call("registerReceiver", context, "AppIntegrityError"); // Only available when ONEShield Threat Events are enabled } }
- Place these scripts in Assets/Scripts.
Compatibility with Android 14
Unity compatibility with Android 14 is seamless. The code sample provided above utilizes native platform implementations, ensuring that no modifications are needed to make your app fully compatible with Android 14.
Special Considerations
- Replace the event identifiers in your ThreatEventsImp according to the selections you made while fusing the application. To find the relevant Threat-Event context key, search for the specific feature via our knowledge base and navigate to the code sample section in the relevant article.
- You can stack multiple listeners for various events for comprehensive threat detection and response capabilities.
- For detailed information on advanced usage and alternative methods of implementation, please refer to the official documentation on the Native Android Plugin, BroadcastReceiver, and NSNotificationCenter.
Meta-Data for Mobile Application Threat-Events and Threat-Scores
Below is the list of metadata that can be associated with each mobile application, Threat-Event, and Threat-Score in Unity Apps.
Threat-Event Context Keys
message
Message displayed for the user on event
failSafeEnforce
Timed enforcement against the identified threat
externalID
The external ID of the event which can be listened via Threat Events
osVersion
OS version of the current device
deviceModel
Current device model
deviceManufacturer
The manufacturer of the current device
fusedAppToken
The task ID of the Appdome fusion of the currently running app
kernelInfo
Info about the kernel: system name, node name, release, version and machine.
deviceID
Current device ID
reasonCode
Reason code of the occurred event
buildDate
Appdome fusion date of the current application
devicePlatform
OS name of the current device
updatedOSVersion
Is the OS version up to date
timeZone
Time zone
deviceFaceDown
Is the device face down
locationLong
Location longitude conditioned by location permission
locationLat
Location latitude conditioned by location permission
locationState
Location state conditioned by location permission
wifiSsid
Wifi SSID
wifiSsidPermissionStatus
Wifi SSID permission status
At the discretion of the mobile developer, Unity Apps can consume some or all of the meta-data for each mobile application Threat-Event and Threat-Score and use it in combination with other mobile application data to modify the business logic or user experience when one or more attacks or threats are present.
Using Conditional Enforcement for Mobile Application Threat-Events and Threat-Scores
Conditional Enforcement is an extension of Appdome’s mobile application Threat-Event framework. By using conditional enforcement, developers can control when Appdome enforcement of each mobile application protection takes place or invoke backup, failsafe, and enforcement to any in-app enforcement used by the mobile developer.
Verifying Threat Events in Unity Apps
After you have implemented the required Threat-Event code in your Unity Apps, you can confirm that the Appdome protections in the Unity Apps properly recognize your Threat-Event implementation by reviewing the Certified Secure™ DevSecOps certificate for your build on Appdome.
The Certified Secure DevSecOps certificate displays an incorrect implementation of Threat Events in your mobile application, as shown below.
For more information on how to retrieve the Certified Secure DevSecOps certification for your mobile application on Appdome, please visit the knowledge base article: Using Certified Secure™ Android & iOS Apps Build Certification in DevOps CI/CD
Related Articles
- Threat-Events™, In-App Threat Intelligence in Kotlin Apps
- Threat-Events™, In-App Threat Intelligence in Flutter Apps
- Threat-Events™, In-App Threat Intelligence in Native iOS Apps
- Threat-Events™, In-App Threat Intelligence in React Native Apps
- Threat-Events™, In-App Threat Intelligence in Swift Apps
- Threat-Events™, In-App Threat Intelligence in Native Android Apps
- Threat-Events™, In-App Threat Intelligence in Maui, Xamarin Apps
- Implementing Threat Events – Best Practices
- How To Implement Threat-Events in Java
Thank you!
Thanks for visiting Appdome! Our mission is to secure every app on the planet by making mobile app security easy. We hope we’re living up to the mission with your project.