logo
0
0
WeChat Login
refactor(runtime)!: rename namespace to GameFrameX.SystemInfo.Runtime

GameFrameX Logo

BlankDeviceUniqueIdentifier

Version License Documentation

All-in-One Solution for Indie Game Development · Empowering Indie Developers' Dreams

📖 Documentation🚀 Quick Start


🌐 Language: English | 简体中文 | 繁體中文 | 日本語 | 한국어


A lightweight Unity3D plugin for retrieving device unique identifiers across Android and iOS platforms. It provides a unified C# API to access OAID, IDFA, IMEI, and a stable hardware fingerprint — with zero native dependencies on Android.

Highlights

  • Pure C# on Android — Uses AndroidJavaClass / AndroidJavaObject (JNI) to call system APIs and vendor SDKs directly. No Java code, no JAR files, no Gradle configuration needed.
  • Cross-platform — Works seamlessly on Android, iOS, and the Unity Editor. Unsupported APIs gracefully fall back to SystemInfo.deviceUniqueIdentifier.
  • Vendor-wide OAID — Supports MSA SDK, Huawei, Xiaomi, OPPO, vivo, and Samsung OAID retrieval on Android via reflection.
  • iOS IDFA & SSKeychain — Retrieves IDFA via ASIdentifierManager with ATT support; persists device ID in the Keychain so it survives app reinstalls.
  • Zero mandatory permissions — No permissions required. Optional permissions can be declared to improve identifier uniqueness.
  • Built-in caching — All results are cached in PlayerPrefs after the first call, avoiding redundant system queries.

Features

APIDescriptionReturn Value
DeviceGetOaidGet device OAID (Android only)Raw OAID (stripped -, max 32 chars)
DeviceGetIdfaGet device IDFA (iOS only)Raw IDFA (stripped -, max 32 chars)
DeviceGetImeiGet device IMEIRaw IMEI (stripped -, max 32 chars)
DeviceUniqueIdentifierGet device unique machine IDMD5 hash (32-char hex string)

All APIs cache results via PlayerPrefs. System interfaces are not called again after the first retrieval.

Platform Implementation

PlatformDeviceGetOaidDeviceGetIdfaDeviceGetImeiDeviceUniqueIdentifier
AndroidJNI reflection (MSA / Huawei / Xiaomi / OPPO / vivo / Samsung)SystemInfo.deviceUniqueIdentifier (fallback)JNI call to TelephonyManagerMD5 of IMEI + hardware info + Android ID + WLAN MAC + BT MAC
iOSSystemInfo.deviceUniqueIdentifier (fallback)ASIdentifierManager.advertisingIdentifiernative __DeviceGetIMEI() (IDFV)native DeviceUniqueId() (SSKeychain)
Editor / OtherSystemInfo.deviceUniqueIdentifierSystemInfo.deviceUniqueIdentifierSystemInfo.deviceUniqueIdentifierSystemInfo.deviceUniqueIdentifier

Permissions (Optional)

This plugin does not require any permissions. It gracefully degrades without them. The plugin does not ship with an AndroidManifest.xml. The following permissions should be declared in the consuming project's AndroidManifest.xml as needed.

Android

PermissionImproves DeviceUniqueIdentifier uniquenessImproves DeviceGetImei uniqueness
READ_PHONE_STATEIMEI included in hashCan retrieve real IMEI
ACCESS_WIFI_STATEWLAN MAC included in hash-
BLUETOOTHBluetooth MAC included in hash-
<!-- Add to the consuming project's AndroidManifest.xml as needed -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />

iOS

ConfigPurpose
NSUserTrackingUsageDescriptionATT authorization description required for IDFA
<!-- Add to the consuming project's Info.plist -->
<key>NSUserTrackingUsageDescription</key>
<string>Your advertising identifier will be used to provide better services</string>

Usage Examples

using GameFrameX.SystemInfo.Runtime;

// Get device OAID (Android only, falls back to SystemInfo.deviceUniqueIdentifier on iOS/Editor)
string oaid = BlankDeviceUniqueIdentifier.DeviceGetOaid;

// Get device IDFA (iOS only, falls back to SystemInfo.deviceUniqueIdentifier on Android/Editor)
string idfa = BlankDeviceUniqueIdentifier.DeviceGetIdfa;

// Get device IMEI
string imei = BlankDeviceUniqueIdentifier.DeviceGetImei;

// Get device unique identifier
string deviceId = BlankDeviceUniqueIdentifier.DeviceUniqueIdentifier;

iOS IDFA Notes

IDFA requires user authorization via ATT (App Tracking Transparency). Add to Info.plist before use:

<key>NSUserTrackingUsageDescription</key>
<string>Your advertising identifier will be used to provide better services</string>

And request authorization before calling DeviceGetIdfa:

#if UNITY_IOS || UNITY_IPHONE
// iOS 14+ requires ATT authorization first
if (UnityEngine.iOS.Device.systemVersion.CompareTo("14") >= 0)
{
    UnityEngine.iOS.Device.RequestUserAuthorization(UnityEngine.iOS.UserTracking.Authorization);
}
#endif
string idfa = BlankDeviceUniqueIdentifier.DeviceGetIdfa;

When unauthorized, DeviceGetIdfa returns an empty string without crashing.

Directory Structure

Plugins/
  iOS/
    BlankDeviceUniqueIdentifier/
      AHDeviceUniqueIdentifier.h               # iOS native header
      AHDeviceUniqueIdentifier.mm              # iOS native implementation
      SSKeychain.h                              # SSKeychain keychain utility
      SSKeychain.m
Runtime/
  BlankDeviceUniqueIdentifier.cs               # C# unified interface (Android uses JNI to call system APIs directly, no Java/JAR needed)

On Android, AndroidJavaClass / AndroidJavaObject is used to call system APIs and vendor SDKs directly — no Java code compilation or JAR files required.

License

This project is licensed under the Apache License 2.0.

Copyright 2023 ALianBlank (alianblank@outlook.com)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.