酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Xamarin.iOSでiOSデバイスの機種名(モデル名)を取得する

iOSデバイスも当初と比較するとiPad、iPod、iPhoneとそれぞれの派生モデルが複数登場してきました。搭載されているメモリや画面サイズなどアプリによって適切な表現方法が異なるケースがよくあります。

Objective-Cを使ってモデル名(機種名)を取得する方法は下記の通り過去に紹介したことがあります。

下記のコードのように、システム情報を取得するsysctlbyname関数を使用していました*1

+ (NSString *) platform{
    size_t size;
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    char *machine = malloc(size);
    sysctlbyname("hw.machine", machine, &size, NULL, 0);
    NSString *platform = [NSString stringWithUTF8String:machine];
    free(machine);
    return platform;
}

本記事では、上記のコードをXamarin.iOSでモデル名(機種名)を取得する方法について紹介します。Xamarin.iOSにはClassic API(旧)とUnified API(新)があり、以下のサンプルコードはUnified APIの方での実装になります。

sysctlbyname関数をP/Invokeで実行する際の記述の仕方が異なるようで少しハマってしまいました。

using System;
using System.Runtime.InteropServices;

namespace Softbuild.Hardware
{
    public class DeviceModel
    {
        public const string HardwareProperty = "hw.machine";

        [DllImport ("libc", CallingConvention = CallingConvention.Cdecl)]
        static internal extern int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string property,
            IntPtr output, IntPtr oldLen, IntPtr newp, uint newlen);

        public static string GetModelName()
        {
            var deviceVersion = string.Empty;

            var pLength = IntPtr.Zero;
            var pString = IntPtr.Zero;
            try
            {
                pLength = Marshal.AllocHGlobal(sizeof(int));
                sysctlbyname(DeviceModel.HardwareProperty, IntPtr.Zero, pLength, IntPtr.Zero, 0);
                var length = Marshal.ReadInt32(pLength);
                if (length <= 0)
                {
                    return string.Empty;
                }

                pString = Marshal.AllocHGlobal(length);
                sysctlbyname(DeviceModel.HardwareProperty, pString, pLength, IntPtr.Zero, 0);

                deviceVersion = Marshal.PtrToStringAnsi(pString);
            }
            finally
            {
                if (pLength != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pLength);
                }
                if (pString != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pString);
                }
            }

            return deviceVersion;
        }

    }
}

DeviceModel.GetModelNameメソッドを実行するとiPhone 7,1などのモデル名(機種名)を取得することができますので、この値を元にiPhone 6 plusiPhone 5sと言ったようにモデル名を特定することが可能です。