Android - App Hash - Monitor (Pro)
You can validate the hash of the whole app to ensure that the entire binary, and so the app itself, has not been tampered with. This validation is slightly more complex, as you need to compare the local hash of the application with a remote hash to check its integrity.
Monitor
The 'AndroidPackageHashMonitor' (class AndroidPackageHashMonitor, namespace GUPS.AntiCheat.Monitor.Android) calculates the hash of the entire app (APK/AAB) at runtime. When the hash has been calculated, it emits an AndroidHashStatus to its observers. This hash can then be compared with a remote source to detect whether the app is in its original state or has been modified.
Status
The monitor emits an AndroidHashStatus, which implements IAndroidStatus (and therefore IWatchedSubject):
public struct AndroidHashStatus : IAndroidStatus
{
// True if the hash could not be retrieved (e.g. a JNI failure).
public bool FailedToRetrieveData { get; }
// The algorithm used to compute the hash.
public string Algorithm { get; }
// The hex-encoded hash of the running app (APK/AAB).
public string Hash { get; }
}
- FailedToRetrieveData: True when the hash could not be retrieved or an exception occurred; the other values are then not valid.
- Algorithm: The hash algorithm used (see the table below).
- Hash: The hex-encoded hash of the whole app.
Lifecycle and timing
The monitor calculates the app hash once, in its OnStart callback, and then notifies observers a single time with the resulting AndroidHashStatus. If the hash could not be calculated, it still notifies with FailedToRetrieveData set to true.
Configuration
The algorithm is configured in the AntiCheat project settings rather than on the component. See 'Hash Algorithm' below.
Development builds
The paired detector honors the global 'Verify development builds' switch. By default it validates the app only in release builds, so the check is skipped in development builds and inside the Unity editor. Enable this option in 'Project Settings -> GuardingPearSoftware -> AntiCheat' while testing.

Enable 'Verify development builds' to also validate the app in development builds and the editor.
Supported Platforms
The monitor is only available on Android platforms.
Requirements
Requires an Android build with at least Android 4.4 (API level 19) (December 2013).
How To Use
Attach the 'AndroidPackageHashMonitor' to a child GameObject of the 'AntiCheat-Monitor', assign the used hash algorithm in the 'AntiCheat-Project Settings', and pair it with the 'AndroidPackageTamperingDetector'.
Add Monitor Component
Add the 'AndroidPackageHashMonitor' MonoBehavior from the 'GUPS.AntiCheat.Monitor.Android' namespace to your 'AntiCheat-Monitor' GameObject, or better, to a child GameObject.

Add the 'AndroidPackageHashMonitor' as a Component.
Hash Algorithm
To calculate the app hash, an algorithm is needed. AntiCheat supports the following algorithms:
| Hash-Algorithm | Description |
|---|---|
| None | No hash algorithm is used. |
| MD5 | MD5 hash algorithm. Not recommended for security purposes. |
| SHA1 | SHA1 hash algorithm. Not recommended for security purposes. |
| SHA256 | SHA256 hash algorithm. |
| SHA384 | SHA384 hash algorithm. |
| SHA512 | SHA512 hash algorithm. |
To assign the algorithm used for the app hash calculation, go to 'Project Settings -> GuardingPearSoftware -> AntiCheat'. Go to the section 'Android - App Hash - Settings'. Activate the 'Verify app hash' checkbox and assign the algorithm you would like to use. SHA256 is the recommended algorithm.

In the AntiCheat Project Settings, assign the algorithm used for hashing.
Consume the status in code
Besides pairing the monitor with a detector, you can subscribe your own observer to receive the AndroidHashStatus directly. Every monitor derives from AMonitor and exposes Subscribe(IObserver<IWatchedSubject>), which returns an IDisposable you can dispose to unsubscribe.
using System;
using GUPS.AntiCheat.Core.Watch;
using GUPS.AntiCheat.Monitor.Android;
using UnityEngine;
public class AndroidHashStatusLogger : MonoBehaviour, IObserver<IWatchedSubject>
{
private void Start()
{
var monitor = GetComponentInChildren<AndroidPackageHashMonitor>();
monitor.Subscribe(this);
}
public void OnNext(IWatchedSubject subject)
{
if (subject is AndroidHashStatus status)
{
if (status.FailedToRetrieveData)
{
Debug.LogWarning("Could not calculate the app hash.");
return;
}
Debug.Log($"App hash ({status.Algorithm}): {status.Hash}");
}
}
public void OnError(Exception error) { }
public void OnCompleted() { }
}
Detect Invalid Hash
To react to the sent status and thus validate the calculated hash, you need a detector. To do this, use the 'AndroidPackageTamperingDetector', an aggregated detector that can react to various attempts to tamper with the Android app itself.