UIDevice uniqueIdentifier deprecated - What to do now?

后端 未结 30 2214
日久生厌
日久生厌 2020-11-21 06:07

It has just come to light that the UIDevice uniqueIdentifier property is deprecated in iOS 5 and unavailable in iOS 7 and above. No alternative method or pr

相关标签:
30条回答
  • 2020-11-21 06:27

    The MAC address can be spoofed which makes such an approach useless for tying content to specific users or implementing security features like blacklists.

    After some further research it appears to me that we're left without a proper alternative as of now. I seriously hope Apple will reconsider their decision.

    Maybe it would be a good idea to email Apple about this topic and / or file a bug / feature request on this since maybe they are not even aware of the full consequences for developers.

    0 讨论(0)
  • 2020-11-21 06:27

    Following code helps to get UDID:

            udid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
            NSLog(@"UDID : %@", udid);
    
    0 讨论(0)
  • 2020-11-21 06:28

    This is code I'm using to get ID for both iOS 5 and iOS 6, 7:

    - (NSString *) advertisingIdentifier
    {
        if (!NSClassFromString(@"ASIdentifierManager")) {
            SEL selector = NSSelectorFromString(@"uniqueIdentifier");
            if ([[UIDevice currentDevice] respondsToSelector:selector]) {
                return [[UIDevice currentDevice] performSelector:selector];
            }
        }
        return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
    }
    
    0 讨论(0)
  • 2020-11-21 06:28

    A working way to get UDID:

    1. Launch a web server inside the app with two pages: one should return specially crafted MobileConfiguration profile and another should collect UDID. More info here, here and here.
    2. You open the first page in Mobile Safari from inside the app and it redirects you to Settings.app asking to install configuration profile. After you install the profile, UDID is sent to the second web page and you can access it from inside the app. (Settings.app has all necessary entitlements and different sandbox rules).

    An example using RoutingHTTPServer:

    import UIKit
    import RoutingHTTPServer
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        var bgTask = UIBackgroundTaskInvalid
        let server = HTTPServer()
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            application.openURL(NSURL(string: "http://localhost:55555")!)
            return true
        }
    
        func applicationDidEnterBackground(application: UIApplication) {
            bgTask = application.beginBackgroundTaskWithExpirationHandler() {
                dispatch_async(dispatch_get_main_queue()) {[unowned self] in
                    application.endBackgroundTask(self.bgTask)
                    self.bgTask = UIBackgroundTaskInvalid
                }
            }
        }
    }
    
    class HTTPServer: RoutingHTTPServer {
        override init() {
            super.init()
            setPort(55555)
            handleMethod("GET", withPath: "/") {
                $1.setHeader("Content-Type", value: "application/x-apple-aspen-config")
                $1.respondWithData(NSData(contentsOfFile: NSBundle.mainBundle().pathForResource("udid", ofType: "mobileconfig")!)!)
            }
            handleMethod("POST", withPath: "/") {
                let raw = NSString(data:$0.body(), encoding:NSISOLatin1StringEncoding) as! String
                let plistString = raw.substringWithRange(Range(start: raw.rangeOfString("<?xml")!.startIndex,end: raw.rangeOfString("</plist>")!.endIndex))
                let plist = NSPropertyListSerialization.propertyListWithData(plistString.dataUsingEncoding(NSISOLatin1StringEncoding)!, options: .allZeros, format: nil, error: nil) as! [String:String]
    
                let udid = plist["UDID"]! 
                println(udid) // Here is your UDID!
    
                $1.statusCode = 200
                $1.respondWithString("see https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/iPhoneOTAConfiguration/ConfigurationProfileExamples/ConfigurationProfileExamples.html")
            }
            start(nil)
        }
    }
    

    Here are the contents of udid.mobileconfig:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
        <dict>
            <key>PayloadContent</key>
            <dict>
                <key>URL</key>
                <string>http://localhost:55555</string>
                <key>DeviceAttributes</key>
                <array>
                    <string>IMEI</string>
                    <string>UDID</string>
                    <string>PRODUCT</string>
                    <string>VERSION</string>
                    <string>SERIAL</string>
                </array>
            </dict>
            <key>PayloadOrganization</key>
            <string>udid</string>
            <key>PayloadDisplayName</key>
            <string>Get Your UDID</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>PayloadUUID</key>
            <string>9CF421B3-9853-9999-BC8A-982CBD3C907C</string>
            <key>PayloadIdentifier</key>
            <string>udid</string>
            <key>PayloadDescription</key>
            <string>Install this temporary profile to find and display your current device's UDID. It is automatically removed from device right after you get your UDID.</string>
            <key>PayloadType</key>
            <string>Profile Service</string>
        </dict>
    </plist>
    

    The profile installation will fail (I didn't bother to implement an expected response, see documentation), but the app will get a correct UDID. And you should also sign the mobileconfig.

    0 讨论(0)
  • 2020-11-21 06:28

    We can use identifierForVendor for ios7,

    -(NSString*)uniqueIDForDevice
    {
        NSString* uniqueIdentifier = nil;
        if( [UIDevice instancesRespondToSelector:@selector(identifierForVendor)] ) { // >=iOS 7
            uniqueIdentifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
        } else { //<=iOS6, Use UDID of Device       
                CFUUIDRef uuid = CFUUIDCreate(NULL);
                //uniqueIdentifier = ( NSString*)CFUUIDCreateString(NULL, uuid);- for non- ARC
                uniqueIdentifier = ( NSString*)CFBridgingRelease(CFUUIDCreateString(NULL, uuid));// for ARC
                CFRelease(uuid);
             }
        }
    return uniqueIdentifier;
    }
    

    --Important Note ---

    UDID and identifierForVendor are different:---

    1.) On uninstalling  and reinstalling the app identifierForVendor will change.
    
    2.) The value of identifierForVendor remains the same for all the apps installed from the same vendor on the device.
    
    3.) The value of identifierForVendor also changes for all the apps if any of the app (from same vendor) is reinstalled.
    
    0 讨论(0)
  • 2020-11-21 06:28

    Apple has hidden the UDID from all public APIs, starting with iOS 7. Any UDID that begins with FFFF is a fake ID. The "Send UDID" apps that previously worked can no longer be used to gather UDID for test devices. (sigh!)

    The UDID is shown when a device is connected to XCode (in the organizer), and when the device is connected to iTunes (although you have to click on 'Serial Number' to get the Identifier to display.

    If you need to get the UDID for a device to add to a provisioning profile, and can't do it yourself in XCode, you will have to walk them through the steps to copy/paste it from iTunes.

    Is there a way since (iOS 7's release) to get the UDID without using iTunes on a PC/Mac?

    0 讨论(0)
提交回复
热议问题