欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity功能记录(二十) ------ 获取Android与ios唯一设备标识码UUID

程序员文章站 2022-05-17 08:07:52
...

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与ios唯一设备标识码UUID

 

三.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回调回来的第一个参数自己要修改,否则是不会回调到你的函数的

 

参考 :

SystemInfo获取系统参数