Threat-Events™, In-App Threat Intelligence in Unity Apps with Native Android

Last updated June 2, 2024 by Appdome

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

  1. Enable Threat-Events
    • Select the checkbox next to Threat-Events for the desired runtime protection.
    • This enables (turns ON) Threat-Events for that feature.
  2. 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.

Rootdetect Ui Te

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:

  1. 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.
  2. Unity’s APIs: Unity offers built-in APIs (`UnityEngine.Android`) to access device features directly from Unity scripts.
  3. Third-Party Packages: Explore Unity Package Manager or the Asset Store for pre-built solutions that simplify communication with Android platforms.
  4. 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:

  1. Create a new Java file named JavaBroadcastReceiverInterface.java.
  2. 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);
    }
    
  3. Create a new Java file named JavaBroadcastReceiver.java.
  4. 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));      
        }
    }
    
  5. Create an Android Archive (.aar) from these files.
  6. Place the archive in Assets/Plugins/Android.

C# Scripts:

  1. Create a new C# script named UnityBroadcastProxy.cs.
  2. 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;
            }
        }
    }
  3. Create a new C# script named ThreatEventsImp.cs.
  4. 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
        }
    }
  5. 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
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.
carrierPlmn PLMN of the device
deviceID Current device ID
reasonCode Reason code of the occured event
buildDate Appdome fusion date of the current application
devicePlatform OS name of the current device
carrierName Carrier 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.

Missing Te

The Certified Secure DevSecOps certificate displays an incorrect implementation of Threat Events in your mobile application, as shown below.

Certificate Root Detection Missing Te

 

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

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.

Appdome

Want a Demo?

Threat-Events™ UX/UI Control

GilWe're here to help
We'll get back to you in 24 hours to schedule your demo.