16

Since one release binary will run on pc, xbox and phones, I need a way to fetch the device type on runtime.

It is doable by checking with the ApiInformation for present types, methods etc., but I believe there should be a more reliable way.

Darius V
  • 583
  • 1
  • 4
  • 18

7 Answers7

9

Currently (with the preview tools released 23-Mar-2015) there isn't an easy way to do this, other than (as you mention) using the ApiInformation methods to detect implementations of things that only exist on the specific platform you're after.

It would be nice if there were some helpers to do this and if none are in the final tooling I'm sure some will be created by helpful people in the community.

However, there is a really good reason not to have this in that it encourages broad assumptions about the device.

If it was possible to say "Am I running on a phone?" then if you got the response 'Yes' then it would be easy to make assumptions about what was possible with that device but not all phones have the same capabilities.
It looks like there will be a "mobile" version of Windows 10 for both phones and small tablets. If you were able to say "am I the 'mobile' version?" then again that wouldn't potentially answer all your questions and you'd have to still check individual API availabilities as the capabilities of a cheap tablet and a high end phone could be vastly different. (The inclusion of physical buttons on the device and the ability to make phone calls are two obvious examples.) Extending this further there are plenty of scenarios where you'd treat different platforms the same as the functionality exists on all of them. In this scenario you're code would be better of saying "Is such and such API available?", rather than saying "Am I running on desktop, Xbox or SurfaceHub?".
The IOT platform will likely further complicate this due to the range of functionality and capabilities different IOT devices will have available.

There are very few scenarios where you want to know the platform you're running on and not whether a specific API is available. Hopefully, by only exposing API availability Microsoft are encouraging developers to think about checking for what they actually need, rather than relying on broad, potentially incomplete, classifications of devices.

Just as with web development where you don't know what platform or browser you are running on, you shouldn't detect the platform and make assumptions about what capabilities that device will therefore have, you should detect if the specific capability you require is supported/enabled on the device before using it or exposing associated UI in your app.

Matt Lacey
  • 65,560
  • 11
  • 91
  • 143
  • 1
    A simple realistic scenario where you may need this: you have made multiple apps (some run on everything, some only on specific types of devices) and you make a universal "about" dialog for all of your apps with a part promoting your other apps. But when current app runs on the phone you don't want to promote apps that run only on desktop and the other way around. – Alan Mendelevich Mar 26 '15 at 12:31
  • 1
    Also - I'm guessing you would create a different layout for say a phablet ( so a phone with large screen ) than for a small tablet. Not sure what scenario, but gut feeling tells me there could be some occasions you want to split them – Depechie Mar 26 '15 at 14:52
  • General guidance is good (you typically don't want to know if you're on a phone) but if you do really need to know, there is a better way than using `ApiInformation` as I note below - use MRT instead. – Peter Torr - MSFT Apr 01 '15 at 06:20
7

[Edit July 3 to replace //build-era information with current information]

Although you can try and infer the device you're on by using the ApiInformation APIs to detect APIs, this is a very bad solution since APIs can be added to devices over time. Please don't do that; your future self (or your replacement ;-) ) will thank you.

If you really do need to programmatically detect the device family that you're running on (and in most cases you don't) then you can use AnalyticsInfo.VersionInfo.DeviceFamliy. This returns a string for which there is no published standard set of values, because device families could be introduced or retired at any time.

If you want to provide different resources per device-family (strings, images, XAML files, HTML pages, etc.) then you don't need to detect the device-family in code; instead you can use an MRT qualifier DeviceFamily (such as Logo.DeviceFamily-Mobile.png). Just make sure you always have a fallback resource (image, string, etc) for use when the app is running on a device family you've never heard of before. And don't fall into the trap of assuming things like "Desktop requires higher-res assets than Mobile" because that is often not true.

Peter Torr - MSFT
  • 11,824
  • 3
  • 18
  • 51
  • This doesn't seem to work for me. :( I have a file named Sketch1.DeviceFamily-Desktop.scale-125.png and a file named Sketch1.scale-100.png and on desktop, the unqualified one loads. – Shahar Prish Nov 18 '15 at 17:26
  • 1
    Is the device 100% scale? That might have a higher priority than the device-family. – Peter Torr - MSFT Nov 18 '15 at 18:54
  • Yeah - 100% scale. So I can only have 1 qualifier? Does that mean that if I want to have multiple scale factors for an image on desktop AND phone, I can't use automatic resolution and instead do it manually? – Shahar Prish Nov 18 '15 at 18:56
  • 1
    No you can have many qualifiers, it is just that some have higher precedence than others (eg language it's more important than scale). This seems like the wrong priority though... – Peter Torr - MSFT Nov 19 '15 at 04:30
  • Oh! Sorry -> I copied over the wrong file name. I also have a file called sketch1.DeviceFamily-Desktop.scale-100 - and that doesn't work either. I had to rename the file to sketch1.DeviceFamily-Desktop.png and that's the only thing that worked (but of course, now I don't have scaling factored in when the image is chosen) – Shahar Prish Nov 19 '15 at 05:39
7

It seems there is a new API to detect Device Family: Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily

You can find more information here: https://msdn.microsoft.com/en-us/library/windows/apps/dn705767.aspx

Updated:

https://msdn.microsoft.com/en-us/library/windows/apps/windows.system.profile.analyticsversioninfo.aspx

Community
  • 1
  • 1
pauliusnrk
  • 593
  • 7
  • 18
  • 1
    worth noting the link is broken :( – bc3tech Sep 01 '15 at 18:06
  • 3
    The purpose of the ``Windows.System.Profile`` ``AnalyticsInfo`` properties is for diagnostic logging. You should treat them as opaque strings that you *do not parse at runtime on the client*. Relying on this as your platform detection is brittle. – Chuck Walbourn Oct 16 '15 at 16:54
4

Additionally to support the scenario Alan describes in his comment you can check for a Contract rather than a specific type as this indicates a block of related functionality. There is one such contract for the Windows Phone specific APIs - I described in here http://inthehand.com/2015/03/26/determine-if-running-on-windows-phone-from-a-uap-application/ Since this contract provides compatibility APIs for current Windows Phone apps we can assume at this point that it won't be implemented in small tablets as they won't have this. Obviously since the OS or APIs are not final this is not set in stone yet. This is a useful thing to know for Windows Phone especially if during the transition you want to cross promote legacy WP apps only on WP devices. For custom IoT devices I would check availability at the API level.

Peter Foot
  • 76
  • 2
2

You can specify device family exclusive resources and views using specially named folders: (http://www.sharpgis.net/post/2015/04/01/Creating-DeviceFamily-specific-layouts-in-a-Universal-App).

You could, for the "advertising only same family apps" scenario described above, place a JSON or XML file in that device family's folder and fetch it at runtime using the storage API's.

CoreyRalli
  • 724
  • 5
  • 17
2

I use this for phone (mobile):

if (Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily == "Windows.Mobile")
{
      // code for phone 
}
else
{
      // other code
}

extample is here

neosonne
  • 136
  • 1
  • 4
  • Can you put more of the documentation from the link into your answer to make it more complete? The reason for this is that external links to SO may get broken or go offline after time and when someone comes and finds this question from a search it won't be as relevant if that source goes away. Thanks! – Shawn Oct 16 '15 at 16:53
0

This is just repeating one of the previous answers which suggests using Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily but I thought I'd include the complete code for a check:

// ----------------------------------------------------------------------
// IsRunningOnXbox
// Determines whether or not the game is running on an xbox console
bool IsRunningOnXbox()
{
    // Skip if already checked
    static bool bChecked = false;
    static bool bRunningOnXbox = false;
    if (bChecked)
        return bRunningOnXbox;

    // Retrieve the platform device family
    Platform::String^ strVersionInfoDeviceFamily = Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily;
    if (strVersionInfoDeviceFamily != nullptr)
    {
        // Check to see if the device belongs to the xbox family
        std::wstring strDeviceFamily = strVersionInfoDeviceFamily->Data();
        std::transform(strDeviceFamily.begin(), strDeviceFamily.end(), strDeviceFamily.begin(), ::tolower);
        if (strDeviceFamily.find(L"xbox") != std::wstring::npos)
            bRunningOnXbox = true;
    }

    // Check complete
    bChecked = true;

    // Return whether or not the host platform is xbox
    return bRunningOnXbox;
}

I do agree with Chuck's comment that this is probably not what AnalyticsInfo is intended for... but at the same time, we're talking about the xbox - a device with a single manufacturer who is also responsible for the OS. So in my mind at least, this seems pretty safe. Plus, if you wrap it like this, it's incredibly easy to swap in a different check should something better come along.

FrolickingFerret
  • 291
  • 1
  • 2
  • 12