In some situation we may want to identify different device that the app runs on in order to apply device-specific content or behavior. Original from Windows Phone 7 ago, we got direct solution to retrieve the device unique ID for a WP device, and things were got a little changed (improved) for Windows Phone 8. However, this feature was originally “missing” in the preview version prior to Windows 8 RTM, which were widely asked during our beta support one year ago. I think this could a good topic deserved to be the first article of our “Store App FAQ” series.
(do not forget to add ID_CAP_IDENTITY_DEVICE capability in the app manifest):
byte myDeviceID = (byte)Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("DeviceUniqueId");
string DeviceIDAsString = Convert.ToBase64String(myDeviceID);
There is a remark in this property document Microsoft.Phone.Info.DeviceExtendedProperties:
In Windows Phone OS 7.0, this class was used to query device-specific properties. In Windows Phone OS 7.1, most of the properties in DeviceExtendedProperties were deprecated, and the new DeviceStatus class should be used instead. However, where appropriate, you can still use any of the below properties that are not deprecated.
However, we still have to use DeviceExtendedProperties to retrieve the “DeviceUniqueId”, which is not included in the new Microsoft.Phone.Info.DeviceStatus.
We can surely use the API above, plus a fresh, modern, new API of Windows Phone Runtime - HostInformation.PublisherHostId property which returns a string directly and could be consumed by both .Net language or C++. This winrt API is functionally identical to the “DeviceExtendedProperties”, with a little logic change - For Windows Phone 8 apps running on Windows Phone 8 devices and later, the DeviceUniqueId value is unique per device and per app publisher, which means that two apps published by different windows phone store account won’t get the same “device unique id”.
The concept and objects of App Specific Hardware ID (ASHWID) came with Windows 8 RTM. Unlike a mobile phone, Hardware of a PC or tablet could possibly get minor or major changed, so that a unique id like Windows Phone doesn’t make sense for such scenario. During the preview, when we were asked for such application scenario, we used to provide workarounds like these:
· Generate a GUID randomly when the app launches at the first time;
· Take advantage of Live SDK to associate the app to live ID, given that most of the windows 8 devices could be signed with Microsoft Account.
Fortunately one year ago this article Guidance on using the App Specific Hardware ID (ASHWID) to implement per-device app logic shipped with Windows 8 RTM caught our eyes and does satisfy our requirement. With Windows 8 RTM, we can use Application Specific Hardware Identifier (ASHWID) as a unique and persistent ID for a Windows 8 device. We can use the HardwareIdentification.GetPackageSpecificToken method to generate the token in HardwareToken type.
HardwareToken hwToken = HardwareIdentification.GetPackageSpecificToken(null);
IBuffer hwID = hwToken.Id;
byte hwIDBytes = hwID.ToArray(); //WindowsRuntimeBufferExtensions.ToArray(hwID)
string deviceID = hwIDBytes.Select(b => b.ToString()).Aggregate((b, next) => b + "," + next);
//sample id result : 3,0,188,97,3,0,76,128,3,0,250,138,5,0,220,130,6,0,1,0,4,0,20,164,1,0,204,49,2,0,226,37,9,0,22,72
For the structure of an ASHWID and how each code means, please refer to the guidance on MSDN. In general, the ASHWID provides a strong binding between the app/package and the device by representing several individual hardware characteristics. In order to protect user privacy, the ASHWID varies from app to app. Unless the underlying hardware has changed, two calls from the same app will result in identical ASHWIDs. However, the ASHWID changes if the hardware profile of the device changes, such as when the user unplugs a USB Bluetooth adapter. The back-end cloud service can verify the ASHWID and compare it with previously reported values. Though the ASHWID varies, it can be parsed to detect if the variance was simply due to a minor change such as an addition of memory to the system. And of course, the length of the byte arrary / IBuffer is not fixed.