Unity通过KeyChain获取IOS设备唯一ID

前言,觉得好的同学别忘了给个好评哦,另外,如果有什么疑问的,欢迎随时提问~~

首先是Xcode设置

如下图,申明keychainSharing公告访问区,添加keychainSharing,然后点击+,填入你的包名(bundleID):
申明keychainSharing公告访问区

然后是oc代码

首先要添加系统类库Security.framework,代码里会引用到

BGKeychainTool .h:

#import <Foundation/Foundation.h>
#import <Security/Security.h>

@interface BGKeychainTool : NSObject

/**
 本方法是得到 UUID 后存入系统中的 keychain 的方法
 不用添加 plist 文件
 程序删除后重装,仍可以得到相同的唯一标示
 但是当系统升级或者刷机后,系统中的钥匙串会被清空,此时本方法失效
 */
+(NSString *)getDeviceIDInKeychain;

@end

BGKeychainTool .m:

#import "BGKeychainTool.h"

@implementation BGKeychainTool

+(NSString *)getDeviceIDInKeychain {
    NSString *bundleId =[[NSBundle mainBundle]bundleIdentifier];
    NSString *getUDIDInKeychain = (NSString *)[BGKeychainTool load:bundleId];
    NSLog(@"从keychain中获取到的 UDID_INSTEAD %@",getUDIDInKeychain);
    if (!getUDIDInKeychain ||[getUDIDInKeychain isEqualToString:@""]||[getUDIDInKeychain isKindOfClass:[NSNull class]]) {
        CFUUIDRef puuid = CFUUIDCreate( nil );
        CFStringRef uuidString = CFUUIDCreateString( nil, puuid );
        NSString * result = (NSString *)CFBridgingRelease(CFStringCreateCopy( NULL, uuidString));
        CFRelease(puuid);
        CFRelease(uuidString);
        NSLog(@"\n \n \n _____重新存储 UUID _____\n \n \n  %@",result);
        [BGKeychainTool save:bundleId data:result];
        getUDIDInKeychain = (NSString *)[BGKeychainTool load:bundleId];
    }
    NSLog(@"最终 ———— UDID_INSTEAD %@",getUDIDInKeychain);
    return getUDIDInKeychain;
}

+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (id)kSecClassGenericPassword,(id)kSecClass,
            service, (id)kSecAttrService,
            service, (id)kSecAttrAccount,
            (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
            nil];
}

+ (void)save:(NSString *)service data:(id)data {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef)keychainQuery);
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}

+ (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) {
        ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
    }
    if (keyData)
        CFRelease(keyData);
    return ret;
}

+ (void)delete:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef)keychainQuery);
}
@end

//这个方法是给unity调用的方法
const char * Get_UUID_By_KeyChain()
{
    NSString* uuid = [BGKeychainTool getDeviceIDInKeychain];
    return strdup(uuid.UTF8String);
}

然后是C#调用的代码

using System.Runtime.InteropServices;

public class GetOnlyDeviceID
{
    public static string Get_OnlyID_By_KeyChain()
    {
        return Get_UUID_By_KeyChain();
    }

    [DllImport("__Internal")]
    private static extern string Get_UUID_By_KeyChain();
}


就是这么简单~~!!

最后有一点需要注意一下,如果你的app被转让了,那么teamID就会改变,而KeyChain的数据是保存在teamID下的仓库里面的,所以app转让后你的数据就会丢失。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐