2019年5月30日更新 :
Android功能记录(一) ------ 获取手机唯一标识码
以下方法对于华为手机无效
被坑的好狠~
原本以为SystemInfo.deviceUniqueIdentifier就是设备唯一标识码,谁知道,这个在某些设备上获取的是动态变化的!!!!?
一.Android
/**
* 返回 唯一的虚拟 ID
* @return ID
*/
public void getUniquePsuedoID() {
String m_szDevIDShort = "35" + (Build.BOARD.length() % 10) + (Build.BRAND.length() % 10) + (Build.CPU_ABI.length() % 10) + (Build.DEVICE.length() % 10) + (Build.MANUFACTURER.length() % 10) + (Build.MODEL.length() % 10) + (Build.PRODUCT.length() % 10);
// API >= 9 的设备才有 android.os.Build.SERIAL
// http://developer.android.com/reference/android/os/Build.html#SERIAL
// 如果用户更新了系统或 root 了他们的设备,该 API 将会产生重复记录
String serial = null;
try {
serial = android.os.Build.class.getField("SERIAL").get(null).toString();
UnityPlayer.UnitySendMessage("ScriptHolder","GetUUID",new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString());
return;
} catch (Exception exception) {
serial = "serial";
}
// 最后,组合上述值并生成 UUID 作为唯一 ID
UnityPlayer.UnitySendMessage("ScriptHolder","GetUUID",new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString());
}
调用 :
playerActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = playerActivity.GetStatic<AndroidJavaObject>("currentActivity");
jo.Call("getUniquePsuedoID");
交互参考这里 : Unity功能记录(五)------ Android studio打包aar包后与unity互相通信
二.iOS
UUIDTool.h:
#import <Foundation/Foundation.h>
@interface UUIDTool : NSObject
/**
* 普通的获取UUID的方法
*/
+ (NSString *)getUUID;
/**
* 获取到UUID后存入系统中的keychain中,保证以后每次可以得到相同的唯一标志
* 不用添加plist文件,当程序删除后重装,仍可以得到相同的唯一标示
* 但是当系统升级或者刷机后,系统中的钥匙串会被清空,再次获取的UUID会与之前的不同
* @return keychain中存储的UUID
*/
+ (NSString *)getUUIDInKeychain;
/**
* 删除存储在keychain中的UUID
* 如果删除后,重新获取用户的UUID会与之前的UUID不同
*/
+ (void)deleteKeyChain;
@end
UUIDTool.m:
//
// UUIDTool.m
// ZYUUID
//
// Created by 竹雨 on 2018/4/13.
// Copyright © 2018年 竹雨. All rights reserved.
//
#import "UUIDTool.h"
NSString * const kUUIDKey = @"com.myApp.uuid";
@implementation UUIDTool
// 普通的获取UUID的方法
+ (NSString *)getUUID {
CFUUIDRef puuid = CFUUIDCreate( nil );
CFStringRef uuidString = CFUUIDCreateString(nil, puuid);
NSString *result = (NSString *)CFBridgingRelease(CFStringCreateCopy( NULL, uuidString));
return result;
}
#pragma mark - 获取到UUID后存入系统中的keychain中
+ (NSString *)getUUIDInKeychain {
// 1.直接从keychain中获取UUID
NSString *getUDIDInKeychain = (NSString *)[UUIDTool load:kUUIDKey];
NSLog(@"从keychain中获取UUID%@", getUDIDInKeychain);
// 2.如果获取不到,需要生成UUID并存入系统中的keychain
if (!getUDIDInKeychain || [getUDIDInKeychain isEqualToString:@""] || [getUDIDInKeychain isKindOfClass:[NSNull class]]) {
// 2.1 生成UUID
CFUUIDRef puuid = CFUUIDCreate(nil);
CFStringRef uuidString = CFUUIDCreateString(nil, puuid);
NSString *result = (NSString *)CFBridgingRelease(CFStringCreateCopy(NULL, uuidString));
CFRelease(puuid);
CFRelease(uuidString);
NSLog(@"生成UUID:%@",result);
// 2.2 将生成的UUID保存到keychain中
[UUIDTool save:kUUIDKey data:result];
// 2.3 从keychain中获取UUID
getUDIDInKeychain = (NSString *)[UUIDTool load:kUUIDKey];
}
return getUDIDInKeychain;
}
#pragma mark - 删除存储在keychain中的UUID
+ (void)deleteKeyChain {
[self delete:kUUIDKey];
}
#pragma mark - 私有方法
+ (NSMutableDictionary *)getKeyChainQuery:(NSString *)service {
return [NSMutableDictionary dictionaryWithObjectsAndKeys:(id)kSecClassGenericPassword,(id)kSecClass,service,(id)kSecAttrService,service,(id)kSecAttrAccount,(id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible, nil];
}
// 从keychain中获取UUID
+ (id)load:(NSString *)service {
id ret = nil;
NSMutableDictionary *keychainQuery = [self getKeyChainQuery:service];
[keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
[keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
CFDataRef keyData = NULL;
if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
@try {
ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
}
@catch (NSException *exception) {
NSLog(@"Unarchive of %@ failed: %@", service, exception);
}
@finally {
NSLog(@"finally");
}
}
if (keyData) {
CFRelease(keyData);
}
NSLog(@"ret = %@", ret);
return ret;
}
+ (void)delete:(NSString *)service {
NSMutableDictionary *keychainQuery = [self getKeyChainQuery:service];
SecItemDelete((CFDictionaryRef)keychainQuery);
}
// 将生成的UUID保存到keychain中
+ (void)save:(NSString *)service data:(id)data {
// Get search dictionary
NSMutableDictionary *keychainQuery = [self getKeyChainQuery:service];
// Delete old item before add new item
SecItemDelete((CFDictionaryRef)keychainQuery);
// Add new object to search dictionary(Attention:the data format)
[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
// Add item to keychain with the search dictionary
SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}
@end
#if defined (__cplusplus)
extern "C" {
#endif
void _getUUIDInKeychain()
{
NSString *s = [UUIDTool getUUIDInKeychain];
UnitySendMessage("ScriptHolder","GetUUID",s.UTF8String);
}
# if defined (__cplusplus)
}
#endif
Unity UUIDToolExtern.cs :
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public class UUIDToolExtern
{
#if UNITY_IOS && !UNITY_EDITOR
[DllImport("__Internal")]
private static extern void _getUUIDInKeychain();
public static void getUUIDInKeychain()
{
_getUUIDInKeychain();
}
#endif
}
注意xcode打包时要注意以下设置:
三.unity调用
Android调用 :
#if UNITY_ANDROID && !UNITY_EDITOR
playerActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
jo = playerActivity.GetStatic<AndroidJavaObject>("currentActivity");
jo.Call("getUniquePsuedoID");
#endif
iOS调用:
#if UNITY_IOS && !UNITY_EDITOR
UUIDToolExtern.getUUIDInKeychain();
#endif
最后请注意 :
Android和iOS回调回来的第一个参数自己要修改,否则是不会回调到你的函数的
参考 :