Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Getting True Device Type from iOS - A little how to...



Permlink Replies: 5 - Last Post: Sep 14, 2016 12:28 AM Last Post By: Dave Nottage
Paul Bedford

Posts: 5
Registered: 8/20/11
Getting True Device Type from iOS - A little how to...
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 23, 2016 8:25 AM
I have been wanting to get the true device type from an iOS device in Delphi for some time but never succeeded. I could only extract the device type provided in the demo app which gives 'iPhone' or 'iPad' as a result.

Now I have worked it out and decided to share it in case others what to do this:

First you must install 'ByteStings' from http://andy.jgknet.de/blog/2015/09/byte-strings-for-delphi-10-seattles-mobile-compilers/ so you can use PAnsiChar.

Then add to your uses clause 'System.ByteStrings' and 'Posix.SysSysctl'.

Then the following routine will return the true Device type.

function GetIOSDeviceType: string;
var
	machine: string;
	Size: NativeInt;
	name: PAnsiChar;
begin
	machine := '';
	sysctlbyname('hw.machine', nil, @Size, nil, 0);
//	name := AllocMem(size); - No required - actual commented out but lost comments in copying to forum
	GetMem(name, Size);
	try
		sysctlbyname('hw.machine', name, @Size, nil, 0);
		machine := string(name);
	except
	end;
	result := 'Unknown';
	if (machine = 'iPhone1,1')    then result := 'iPhone 1G';
	if (machine = 'iPhone1,2')    then result := 'iPhone 3G';
	if (machine = 'iPhone2,1')    then result := 'iPhone 3GS';
	if (machine = 'iPhone3,1')    then result := 'iPhone 4';
	if (machine = 'iPhone3,3')    then result := 'Verizon iPhone 4';
	if (machine = 'iPhone4,1')    then result := 'iPhone 4S';
	if (machine = 'iPhone5,1')    then result := 'iPhone 5 (GSM)';
	if (machine = 'iPhone5,2')    then result := 'iPhone 5 (GSM+CDMA)';
	if (machine = 'iPhone5,3')    then result := 'iPhone 5c (GSM)';
	if (machine = 'iPhone5,4')    then result := 'iPhone 5c (GSM+CDMA)';
	if (machine = 'iPhone6,1')    then result := 'iPhone 5s (GSM)';
	if (machine = 'iPhone6,2')    then result := 'iPhone 5s (GSM+CDMA)';
	if (machine = 'iPhone7,2')    then result := 'iPhone 6';
	if (machine = 'iPhone7,1')    then result := 'iPhone 6 Plus';
	if (machine = 'iPhone8,1')    then result := 'iPhone 6s';
	if (machine = 'iPhone8,2')    then result := 'iPhone 6s Plus';
	if (machine = 'iPod1,1')      then result := 'iPod Touch 1G';
	if (machine = 'iPod2,1')      then result := 'iPod Touch 2G';
	if (machine = 'iPod3,1')      then result := 'iPod Touch 3G';
	if (machine = 'iPod4,1')      then result := 'iPod Touch 4G';
	if (machine = 'iPod5,1')      then result := 'iPod Touch 5G';
	if (machine = 'iPad1,1')      then result := 'iPad';
	if (machine = 'iPad2,1')      then result := 'iPad 2 (WiFi)';
	if (machine = 'iPad2,2')      then result := 'iPad 2 (GSM)';
	if (machine = 'iPad2,3')      then result := 'iPad 2 (CDMA)';
	if (machine = 'iPad2,4')      then result := 'iPad 2 (WiFi)';
	if (machine = 'iPad2,5')      then result := 'iPad Mini (WiFi)';
	if (machine = 'iPad2,6')      then result := 'iPad Mini (GSM)';
	if (machine = 'iPad2,7')      then result := 'iPad Mini (GSM+CDMA)';
	if (machine = 'iPad3,1')      then result := 'iPad 3 (WiFi)';
	if (machine = 'iPad3,2')      then result := 'iPad 3 (GSM+CDMA)';
	if (machine = 'iPad3,3')      then result := 'iPad 3 (GSM)';
	if (machine = 'iPad3,4')      then result := 'iPad 4 (WiFi)';
	if (machine = 'iPad3,5')      then result := 'iPad 4 (GSM)';
	if (machine = 'iPad3,6')      then result := 'iPad 4 (GSM+CDMA)';
	if (machine = 'iPad4,1')      then result := 'iPad Air (WiFi)';
	if (machine = 'iPad4,2')      then result := 'iPad Air (Cellular)';
	if (machine = 'iPad4,3')      then result := 'iPad Air';
	if (machine = 'iPad4,4')      then result := 'iPad Mini 2G (WiFi)';
	if (machine = 'iPad4,5')      then result := 'iPad Mini 2G (Cellular)';
	if (machine = 'iPad4,6')      then result := 'iPad Mini 2G';
	if (machine = 'iPad4,7')      then result := 'iPad Mini 3 (WiFi)';
	if (machine = 'iPad4,8')      then result := 'iPad Mini 3 (Cellular)';
	if (machine = 'iPad4,9')      then result := 'iPad Mini 3 (China)';
	if (machine = 'iPad5,3')      then result := 'iPad Air 2 (WiFi)';
	if (machine = 'iPad5,4')      then result := 'iPad Air 2 (Cellular)';
	if (machine = 'AppleTV2,1')   then result := 'Apple TV 2G';
	if (machine = 'AppleTV3,1')   then result := 'Apple TV 3';
	if (machine = 'AppleTV3,2')   then result := 'Apple TV 3 (2013)';
	if (machine = 'i386')         then result := 'Simulator';
	if (machine = 'x86_64')       then result := 'Simulator';
	FreeMem(name);
end;


I have tried this on a number of devices and has always returned the correct result.

Remember to encase in {$IFDEF IOS}...{$ENDIF} if code could be compile for other platforms.

Enjoy.

Hope this helps.

Paul Bedford
Senior Delphi Developer
Kinetic Solutions.

Edited by: Paul Bedford on Feb 24, 2016 12:23 AM
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Getting True Device Type from iOS - A little how to...
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 23, 2016 10:06 AM   in response to: Paul Bedford in response to: Paul Bedford
Paul wrote:

First you must install 'ByteStings' from
http://andy.jgknet.de/blog/2015/09/byte-strings-for-delphi-10-seattles
-mobile-compilers/ so you can use PAnsiChar.

You do not need to use the ByteStrings patch in order to use sysctlbyname()
(not to mention the code you showed has a memory leak - you are allocating
'name' twice, but only freeing it once).

The actual declaration of sysctlbyname() looks like this:

function sysctlbyname(Name: MarshaledAString;
  oldp: Pointer; oldlen: Psize_t;
  newp: Pointer; newlen: size_t): Integer; cdecl;
  external libc name _PU + 'sysctlbyname';


Delphi has TMarshal and TMarshaller classes for working with marshalled strings
in native environments.

http://docwiki.embarcadero.com/Libraries/en/System.TMarshal

http://docwiki.embarcadero.com/Libraries/en/System.SysUtils.TMarshaller

Since the other parameters are plain pointers, you can use either TMarshal/TMarshaller
or TBytes+TEncoding to allocate those buffers and convert them to strings.

Try something more like this:

uses
  ..., System.SysUtils, Posix.SysSysctl;
 
function GetIOSDeviceType: string;
var
  machine: string;
  Size: NativeInt;
  M: TMarshaller;
  name: Pointer;
  buffer: TPtrWrapper;
begin
  machine := '';
  name := M.AsAnsi('hw.machine').ToPointer;
  sysctlbyname(name, nil, @Size, nil, 0);
  buffer := M.AllocMem(size);
  sysctlbyname(name, buffer.ToPointer, @Size, nil, 0);
  machine := TMarshal.ReadStringAsAnsi(buffer);
  if (machine = 'iPhone1,1') then Result := 'iPhone 1G';
  else if (machine = 'iPhone1,2') then result := 'iPhone 3G';
  // and so on ...
  else
    Result := 'Unknown';
end;


Or this:

uses
  ..., System.SysUtils, Posix.SysSysctl;
 
function GetIOSDeviceType: string;
var
  machine: string;
  Size: NativeInt;
  M: TMarshaller;
  name: Pointer;
  buffer: TBytes;
begin
  name := M.AsAnsi('hw.machine').ToPointer;
  sysctlbyname(name, nil, @Size, nil, 0);
  SetLength(buffer, size);
  sysctlbyname(name, Pointer(buffer), @Size, nil, 0);
  machine := TEncoding.Default.GetString(buffer, 0, Size);
  if (machine = 'iPhone1,1') then Result := 'iPhone 1G';
  else if (machine = 'iPhone1,2') then Result := 'iPhone 3G';
  // and so on ...
  else
    Result := 'Unknown';
end;


--
Remy Lebeau (TeamB)
Paul Bedford

Posts: 5
Registered: 8/20/11
Re: Getting True Device Type from iOS - A little how to...
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 24, 2016 12:26 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Paul wrote:

First you must install 'ByteStings' from
http://andy.jgknet.de/blog/2015/09/byte-strings-for-delphi-10-seattles
-mobile-compilers/ so you can use PAnsiChar.

You do not need to use the ByteStrings patch in order to use sysctlbyname()
(not to mention the code you showed has a memory leak - you are allocating
'name' twice, but only freeing it once).

The actual declaration of sysctlbyname() looks like this:

function sysctlbyname(Name: MarshaledAString;
  oldp: Pointer; oldlen: Psize_t;
  newp: Pointer; newlen: size_t): Integer; cdecl;
  external libc name _PU + 'sysctlbyname';


Delphi has TMarshal and TMarshaller classes for working with marshalled strings
in native environments.

http://docwiki.embarcadero.com/Libraries/en/System.TMarshal

http://docwiki.embarcadero.com/Libraries/en/System.SysUtils.TMarshaller

Since the other parameters are plain pointers, you can use either TMarshal/TMarshaller
or TBytes+TEncoding to allocate those buffers and convert them to strings.

Try something more like this:

uses
  ..., System.SysUtils, Posix.SysSysctl;
 
function GetIOSDeviceType: string;
var
  machine: string;
  Size: NativeInt;
  M: TMarshaller;
  name: Pointer;
  buffer: TPtrWrapper;
begin
  machine := '';
  name := M.AsAnsi('hw.machine').ToPointer;
  sysctlbyname(name, nil, @Size, nil, 0);
  buffer := M.AllocMem(size);
  sysctlbyname(name, buffer.ToPointer, @Size, nil, 0);
  machine := TMarshal.ReadStringAsAnsi(buffer);
  if (machine = 'iPhone1,1') then Result := 'iPhone 1G';
  else if (machine = 'iPhone1,2') then result := 'iPhone 3G';
  // and so on ...
  else
    Result := 'Unknown';
end;


Or this:

uses
  ..., System.SysUtils, Posix.SysSysctl;
 
function GetIOSDeviceType: string;
var
  machine: string;
  Size: NativeInt;
  M: TMarshaller;
  name: Pointer;
  buffer: TBytes;
begin
  name := M.AsAnsi('hw.machine').ToPointer;
  sysctlbyname(name, nil, @Size, nil, 0);
  SetLength(buffer, size);
  sysctlbyname(name, Pointer(buffer), @Size, nil, 0);
  machine := TEncoding.Default.GetString(buffer, 0, Size);
  if (machine = 'iPhone1,1') then Result := 'iPhone 1G';
  else if (machine = 'iPhone1,2') then Result := 'iPhone 3G';
  // and so on ...
  else
    Result := 'Unknown';
end;


--
Remy Lebeau (TeamB)

Thanks Remy, I actual lost the comments on my first memory allocation while messing around pasting in to forum.

Will give your new code a try and change above once I have time to test. I used Byte Strings as already in my code, but will give yours a go.

Thanks.

Paul Bedford.
David Millington

Posts: 257
Registered: 5/29/05
Re: Getting True Device Type from iOS - A little how to... [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 24, 2016 6:53 AM   in response to: Paul Bedford in response to: Paul Bedford
Very useful. Thankyou!

Do you have a blog? Writing a blog post (and making sure the blog feed
is on beginend.net first) would gain a bigger audience than the forums.
It makes it google-able too.

Cheers,

David
Emilio Jiménez

Posts: 1
Registered: 8/15/15
Re: Getting True Device Type from iOS - A little how to...
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 13, 2016 2:41 PM   in response to: Paul Bedford in response to: Paul Bedford
Hello, I've been trying to get the Serial number of the ios devices but I can't get my way around it.

Do you know if there is a way to get it?

Thank you.

Paul Bedford wrote:
I have been wanting to get the true device type from an iOS device in Delphi for some time but never succeeded. I could only extract the device type provided in the demo app which gives 'iPhone' or 'iPad' as a result.

Now I have worked it out and decided to share it in case others what to do this:

First you must install 'ByteStings' from http://andy.jgknet.de/blog/2015/09/byte-strings-for-delphi-10-seattles-mobile-compilers/ so you can use PAnsiChar.

Then add to your uses clause 'System.ByteStrings' and 'Posix.SysSysctl'.

Then the following routine will return the true Device type.

function GetIOSDeviceType: string;
var
	machine: string;
	Size: NativeInt;
	name: PAnsiChar;
begin
	machine := '';
	sysctlbyname('hw.machine', nil, @Size, nil, 0);
//	name := AllocMem(size); - No required - actual commented out but lost comments in copying to forum
	GetMem(name, Size);
	try
		sysctlbyname('hw.machine', name, @Size, nil, 0);
		machine := string(name);
	except
	end;
	result := 'Unknown';
	if (machine = 'iPhone1,1')    then result := 'iPhone 1G';
	if (machine = 'iPhone1,2')    then result := 'iPhone 3G';
	if (machine = 'iPhone2,1')    then result := 'iPhone 3GS';
	if (machine = 'iPhone3,1')    then result := 'iPhone 4';
	if (machine = 'iPhone3,3')    then result := 'Verizon iPhone 4';
	if (machine = 'iPhone4,1')    then result := 'iPhone 4S';
	if (machine = 'iPhone5,1')    then result := 'iPhone 5 (GSM)';
	if (machine = 'iPhone5,2')    then result := 'iPhone 5 (GSM+CDMA)';
	if (machine = 'iPhone5,3')    then result := 'iPhone 5c (GSM)';
	if (machine = 'iPhone5,4')    then result := 'iPhone 5c (GSM+CDMA)';
	if (machine = 'iPhone6,1')    then result := 'iPhone 5s (GSM)';
	if (machine = 'iPhone6,2')    then result := 'iPhone 5s (GSM+CDMA)';
	if (machine = 'iPhone7,2')    then result := 'iPhone 6';
	if (machine = 'iPhone7,1')    then result := 'iPhone 6 Plus';
	if (machine = 'iPhone8,1')    then result := 'iPhone 6s';
	if (machine = 'iPhone8,2')    then result := 'iPhone 6s Plus';
	if (machine = 'iPod1,1')      then result := 'iPod Touch 1G';
	if (machine = 'iPod2,1')      then result := 'iPod Touch 2G';
	if (machine = 'iPod3,1')      then result := 'iPod Touch 3G';
	if (machine = 'iPod4,1')      then result := 'iPod Touch 4G';
	if (machine = 'iPod5,1')      then result := 'iPod Touch 5G';
	if (machine = 'iPad1,1')      then result := 'iPad';
	if (machine = 'iPad2,1')      then result := 'iPad 2 (WiFi)';
	if (machine = 'iPad2,2')      then result := 'iPad 2 (GSM)';
	if (machine = 'iPad2,3')      then result := 'iPad 2 (CDMA)';
	if (machine = 'iPad2,4')      then result := 'iPad 2 (WiFi)';
	if (machine = 'iPad2,5')      then result := 'iPad Mini (WiFi)';
	if (machine = 'iPad2,6')      then result := 'iPad Mini (GSM)';
	if (machine = 'iPad2,7')      then result := 'iPad Mini (GSM+CDMA)';
	if (machine = 'iPad3,1')      then result := 'iPad 3 (WiFi)';
	if (machine = 'iPad3,2')      then result := 'iPad 3 (GSM+CDMA)';
	if (machine = 'iPad3,3')      then result := 'iPad 3 (GSM)';
	if (machine = 'iPad3,4')      then result := 'iPad 4 (WiFi)';
	if (machine = 'iPad3,5')      then result := 'iPad 4 (GSM)';
	if (machine = 'iPad3,6')      then result := 'iPad 4 (GSM+CDMA)';
	if (machine = 'iPad4,1')      then result := 'iPad Air (WiFi)';
	if (machine = 'iPad4,2')      then result := 'iPad Air (Cellular)';
	if (machine = 'iPad4,3')      then result := 'iPad Air';
	if (machine = 'iPad4,4')      then result := 'iPad Mini 2G (WiFi)';
	if (machine = 'iPad4,5')      then result := 'iPad Mini 2G (Cellular)';
	if (machine = 'iPad4,6')      then result := 'iPad Mini 2G';
	if (machine = 'iPad4,7')      then result := 'iPad Mini 3 (WiFi)';
	if (machine = 'iPad4,8')      then result := 'iPad Mini 3 (Cellular)';
	if (machine = 'iPad4,9')      then result := 'iPad Mini 3 (China)';
	if (machine = 'iPad5,3')      then result := 'iPad Air 2 (WiFi)';
	if (machine = 'iPad5,4')      then result := 'iPad Air 2 (Cellular)';
	if (machine = 'AppleTV2,1')   then result := 'Apple TV 2G';
	if (machine = 'AppleTV3,1')   then result := 'Apple TV 3';
	if (machine = 'AppleTV3,2')   then result := 'Apple TV 3 (2013)';
	if (machine = 'i386')         then result := 'Simulator';
	if (machine = 'x86_64')       then result := 'Simulator';
	FreeMem(name);
end;


I have tried this on a number of devices and has always returned the correct result.

Remember to encase in {$IFDEF IOS}...{$ENDIF} if code could be compile for other platforms.

Enjoy.

Hope this helps.

Paul Bedford
Senior Delphi Developer
Kinetic Solutions.

Edited by: Paul Bedford on Feb 24, 2016 12:23 AM
Dave Nottage

Posts: 1,850
Registered: 1/7/00
Re: Getting True Device Type from iOS - A little how to...
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 14, 2016 12:28 AM   in response to: Emilio Jiménez in response to: Emilio Jiménez
Emilio Jiménez wrote:

Hello, I've been trying to get the Serial number of the ios devices but I can't get my way around it.

Do you know if there is a way to get it?

They've disabled that. If you need a unique identifier, you should use identifierForVendor, which is a method of
UIDevice. There's some info here about how "unique" it is:

https://developer.apple.com/reference/uikit/uidevice/1620059-identifierforvendor

Example code:

uses
  Macapi.Helpers, iOSapi.UIKit;
 
...
 
  ID := NSStrToStr(TUIDevice.Wrap(TUIDevice.OCClass.currentDevice).identifierForVendor);
 


--
Dave Nottage [TeamB]
Hints, tips and tricks at: http://www.delphiworlds.com/blog
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02