sysctlbyname でデバイスの種類を取得する
iOS で iPad mini 2 とか、そういう識別子がとりたかったんですが、 UIDevice.CurrentDevice だと、 iPad だとか適当な種類しか取れず、どうやって調べるんだろう?ってググったら、
を使えばいいことは割とすぐに出てきます。
で、今をときめく Swift のサンプルなんかは比較的たくさん見つかるんですが、 Xamarin のものについては、あんまり出てきません。出てきたのは、これぐらい。
ところがですね。こいつ、資料としては古くて、いろいろ問題があるんです。
- Unified API じゃない (MonoTouch.Constants.SystemLibraryってもはやない!)
- 64-bit のことがちゃんと考慮されてない (最後の引数が uint)
- 確保したメモリを開放してない(最低)
- というか、p/invoke の使い方がダサい
という、主に最後の理由で、自分で書き直そうって思いました。
SysCtl.HwMachine で、内部のモデル識別子が得られます。
これを人間が読める奴に変換したい人は、下のページでググればいいと思います。
おまけで、SysCtl.HwMemSize っていうメモリサイズが取得できる奴も搭載してみました。サンプルですね。
public static class SysCtl { /// <summary> /// Internal model description. /// For the full list of the values, see the following URL: /// https://www.theiphonewiki.com/wiki/Models /// </summary> public static string HwMachine => GetSystemProperty("hw.machine"); /// <summary> /// Memory equiped on the machine. /// </summary> public static long HwMemSize => GetSystemProperty64("hw.memsize"); public static string GetSystemProperty(string name) { IntPtr len64 = IntPtr.Zero; if (sysctlbyname(name, null, ref len64, IntPtr.Zero, IntPtr.Zero) < 0) return null; var len = len64.ToInt32(); if (len == 1) return ""; var buf = new byte[len]; if (sysctlbyname(name, buf, ref len64, IntPtr.Zero, IntPtr.Zero) < 0) return null; return Encoding.ASCII.GetString(buf, 0, len - 1); // removing the terminating \0. } public static long GetSystemProperty64(string name) { long val; var len = new IntPtr(Marshal.SizeOf<long>()); if (sysctlbyname(name, out val, ref len, IntPtr.Zero, IntPtr.Zero) < 0) return -1; return val; } /// <summary> /// https://developer.apple.com/library/ios/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sysctlbyname.3.html /// </summary> /// <param name="property"></param> /// <param name="buffer"></param> /// <param name="oldlenp"></param> /// <param name="_null1"></param> /// <param name="newlen"></param> /// <returns></returns> [DllImport(ObjCRuntime.Constants.SystemLibrary)] static extern int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string property, byte[] buffer, ref IntPtr oldlenp, IntPtr _null1, IntPtr newlen); [DllImport(ObjCRuntime.Constants.SystemLibrary)] static extern int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string property, out long value, ref IntPtr oldlenp, IntPtr _null1, IntPtr newlen); }