Programmatically get own phone number in iOS - ios

Is there any way to get own phone number by standard APIs from iPhone SDK?

At the risk of getting negative marks, I want to suggest that the highest ranking solution (currently the first response) violates the latest SDK Agreement as of Nov 5, 2009. Our application was just rejected for using it. Here's the response from Apple:
"For security reasons, iPhone OS restricts an application (including its preferences and data) to a unique location in the file system. This restriction is part of the security feature known as the application's "sandbox." The sandbox is a set of fine-grained controls limiting an application's access to files, preferences, network resources, hardware, and so on."
The device's phone number is not available within your application's container. You will need to revise your application to read only within your directory container and resubmit your binary to iTunes Connect in order for your application to be reconsidered for the App Store.
This was a real disappointment since we wanted to spare the user having to enter their own phone number.

No, there's no legal and reliable way to do this.
If you find a way, it will be disabled in the future, as it has happened with every method before.

Update: capability appears to have been removed by Apple on or around iOS 4
Just to expand on an earlier answer, something like this does it for me:
NSString *num = [[NSUserDefaults standardUserDefaults] stringForKey:#"SBFormattedPhoneNumber"];
Note: This retrieves the "Phone number" that was entered during the iPhone's iTunes activation and can be null or an incorrect value. It's NOT read from the SIM card.
At least that does in 2.1. There are a couple of other interesting keys in NSUserDefaults that may also not last. (This is in my app which uses a UIWebView)
WebKitJavaScriptCanOpenWindowsAutomatically
NSInterfaceStyle
TVOutStatus
WebKitDeveloperExtrasEnabledPreferenceKey
and so on.
Not sure what, if anything, the others do.

Using Private API you can get user phone number on the following way:
extern NSString* CTSettingCopyMyPhoneNumber();
+(NSString *) phoneNumber {
NSString *phone = CTSettingCopyMyPhoneNumber();
return phone;
}
Also include CoreTelephony.framework to your project.

You cannot use iOS APIs alone to capture the phone number (even in a private app with private APIs), as all known methods of doing this have been patched and blocked as of iOS 11. Even if a new exploit is found, Apple has made clear that they will reject any apps from the app store for using private APIs to do this. See #Dylan's answer for details.
However, there is a legal way to capture the phone number without any user data entry. This is similar to what Snapchat does, but easier, as it does not require the user to type in their own phone number.
The idea is to have the app programmatically send a SMS message to a server with the app’s unique installation code. The app can then query the same server to see if it has recently received a SMS message from a device with this unique app installation code. If it has, it can read the phone number that sent it. Here’s a demo video showing the process. As you can see, it works like a charm!
This is not super easy to set up, but it be configured in a few hours at no charge on a free AWS tier with the sample code provided in the tutorial here.

As you probably all ready know if you use the following line of code, your app will be rejected by Apple
NSString *num = [[NSUserDefaults standardUserDefaults] stringForKey:#"SBFormattedPhoneNumber"];
here is a reference
http://ayeapi.blogspot.com/2009/12/sbformatphonenumber-is-lie.html
you can use the following information instead
NSString *phoneName = [[UIDevice currentDevice] name];
NSString *phoneUniqueIdentifier = [[UIDevice currentDevice] uniqueIdentifier];
and so on
#property(nonatomic,readonly,retain) NSString *name; // e.g. "My iPhone"
#property(nonatomic,readonly,retain) NSString *model; // e.g. #"iPhone", #"iPod Touch"
#property(nonatomic,readonly,retain) NSString *localizedModel; // localized version of model
#property(nonatomic,readonly,retain) NSString *systemName; // e.g. #"iPhone OS"
#property(nonatomic,readonly,retain) NSString *systemVersion; // e.g. #"2.0"
#property(nonatomic,readonly) UIDeviceOrientation orientation; // return current device orientation
#property(nonatomic,readonly,retain) NSString *uniqueIdentifier; // a string unique to each device based on various hardware info.
Hope this helps!

To get you phone number you can read a plist file. It will not work on non-jailbroken iDevices:
NSString *commcenter = #"/private/var/wireless/Library/Preferences/com.apple.commcenter.plist";
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:commcenter];
NSString *PhoneNumber = [dict valueForKey:#"PhoneNumber"];
NSLog([NSString stringWithFormat:#"Phone number: %#",PhoneNumber]);
I don't know if Apple allow this but it works on iPhones.

No official API to do it. Using private API you can use following method:
-(NSString*) getMyNumber {
NSLog(#"Open CoreTelephony");
void *lib = dlopen("/Symbols/System/Library/Framework/CoreTelephony.framework/CoreTelephony",RTLD_LAZY);
NSLog(#"Get CTSettingCopyMyPhoneNumber from CoreTelephony");
NSString* (*pCTSettingCopyMyPhoneNumber)() = dlsym(lib, "CTSettingCopyMyPhoneNumber");
NSLog(#"Get CTSettingCopyMyPhoneNumber from CoreTelephony");
if (pCTSettingCopyMyPhoneNumber == nil) {
NSLog(#"pCTSettingCopyMyPhoneNumber is nil");
return nil;
}
NSString* ownPhoneNumber = pCTSettingCopyMyPhoneNumber();
dlclose(lib);
return ownPhoneNumber;
}
It works on iOS 6 without JB and special signing.
As mentioned creker on iOS 7 with JB you need to use entitlements to make it working.
How to do it with entitlements you can find here:
iOS 7: How to get own number via private API?

AppStore will reject it, as it's reaching outside of application container.
Apps should be self-contained in their bundles, and may not read or write data outside the designated container area
Section 2.5.2 :
https://developer.apple.com/app-store/review/guidelines/#software-requirements

Related

Uniquely identify the device in iOS

I am developing a corporate application on the iPad for a certain business requirement.
This app is meant to use in a specific number of devices which is predefined by the admin.
But I also need the application to reject any login requests even if it is from an authorised user,when he or she is using a device which is not defined by the admin.
Edits:
Say I have 2 devices and I have my credentials to login to the app, And my need is, to restrict the login from the devices which is not mine.
For that I have to identify whether the login request is comes from my device or not.
Previously we could use device UDID to do this, but now it is deprecated.
Can any one please suggest a method to implement this ?
try this. for more info check UIDevice
// IOS 6+
NSString *uniqueIdentifier = [[NSString alloc] initWithString:[[[UIDevice currentDevice] identifierForVendor] UUIDString]];
You can use iCloud over here because UUID has been deprecated and vendorId is uniqe but might be change if you uninstall the app and install it agian,
So I would suggest iCloud will be safer, what you cna do is at the time of application launch you can generate one token which is unique and save it to your iCloud data storage along with user credentials,
So from the next time onwards when user will try to login you can check it with iCloud.
How about using Apple's enterprise distribution system? That will allow you to deploy the app to a corporation, and have tight access control.
https://developer.apple.com/programs/ios/enterprise/
Just Trick:
You can Implement APNS code to your Project and Get Device Token.
The Device Token is Unique One. But The user Must Allow the APNS.
Note: APNS Device Token is changed to Following reasons.
Change of Bundle id.
Change of Development Mode(Sandbox/Production)
I have implemented a solution for exactly your problem, The best solution (and Apples recommended route) is to create a UUID unique to your App like this:
NSString *uuidString = nil;
CFUUIDRef uuid = CFUUIDCreate(NULL);
if (uuid) {
uuidString = (NSString *)CFBridgingRelease(CFUUIDCreateString(NULL, uuid));
CFRelease(uuid);
}
Then, and this is the key, you can store that to the iOS keychain (Handy classes here: https://github.com/lukef/IXKeychain) and values in the iOS keychain are NOT removed when the user uninstalls the App, so you can persist your own UUID through App installs which is a key part of managing a specific number of devices against a user account.
This method will return a string for every device. Since it is gonna change every time for single device
so we are storing it in a keychain and can refer it whenever we need it.
+ (NSString *) uniqueDeviceIdentifier
{
NSString *deviceUUID = [[SGKeyChain defaultKeyChain] stringForKey:#"uniqueId"];
if (!deviceUUID) {
if (!deviceUUID.length) {
NSString *deviceUUID = #"";
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
CFRelease(uuidRef);
deviceUUID = [NSString stringWithFormat:#"%#",[NSString stringWithString:(__bridge_transfer NSString *)uuidStringRef]];
[[SGKeyChain defaultKeyChain] setObject:deviceUUID forKey:#"uniqueId" accessibleAttribute:kSecAttrAccessibleAlways];
}
}
return deviceUUID;
}
yo can refer to this repository... https://github.com/sgup77/SGKeyChainWrapper for SGKeyChain implementation
Ok I will share the approach that we follow for a B2B enterprise app.
.
Every User has login Id and Password.
1. So user register his device with Server using deviceReg API which takes clientDeviceId as param(client generated uuid) along with username and pass.
2. Server returns a server generated unique identifier to be used by application on that particular device.
Conclude - in this way you can restrict the user with a certain device.
You can use below method to generate deviceSpecific client UUID
- (NSString *)getUuid
{
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
CFRelease(uuidRef);
NSString *uuid = [NSString stringWithString:(__bridge NSString *)uuidStringRef];
CFRelease(uuidStringRef);
return uuid;
}
Please note:
I remove the explanation about using AuthKey, AccessToken and others which we use for security purpose as you do not use any auth server.
I hope it helps.
Update 1.
Since you are having an enterprise application so i am sure you would be having atleast the user e-mail ids.
So the account manager should than 1st send a email with one time token to all active accounts.
This token can be requested by the application while registering the device and send to server for validation.
Also the server invalidates the token once used to avoid misuge.
There should be a migrAtion api which uses the server generated device id and a migration token if user migrates the device.

Get serial number of device on iOS 8

For an in-house application, we were using the following code UIDevice+serialNumber to get the device serial number.
However, it seems that with iOS 8, the registry key "IOPlatformSerialNumber" is empty.
Can the serial number be obtained any other way?
Answer: No.
There are currently floating solutions around abusing the .mobileconfig, but they add other problems due their nature.
UUID was removed for a reason. See the news around privacy and the summon of Apple by the US Senat from 2011 to gain an understanding why this had to be changed.
http://arstechnica.com/apple/2011/04/apple-google-asked-to-join-judiciary-hearing-on-mobile-device-privacy/
Abusing the underlying march port to get the device serial number as replacement of the UUID is not the solution. Same now for abusing the mobile config and guess how long that will work.
You have plenty of decent ways to handle any situation where you used device identification before. Especial in an enterprise environment where you have cryptography and MDM is absolutely no point to track a device like this.
Retrieving the device serial number directly is no longer possible in iOS.
However, if it's simply for an internal enterprise app, something the company I work for is going to implement is this:
During device configuration, copy the serial number and set the device name as the serial number.
Then use Apple's UIDevice API to retrieve the device name.
As Helger stated above, UDID is no longer available in iOS 6+ due to security / privacy reasons. Instead, use identifierForVendor or advertisingIdentifier
Please check UDID Replacement APIs
For iOS 8+
+ (NSString *)deviceUUID
{
if([[NSUserDefaults standardUserDefaults] objectForKey:[[NSBundle mainBundle] bundleIdentifier]])
return [[NSUserDefaults standardUserDefaults] objectForKey:[[NSBundle mainBundle] bundleIdentifier]];
#autoreleasepool {
CFUUIDRef uuidReference = CFUUIDCreate(nil);
CFStringRef stringReference = CFUUIDCreateString(nil, uuidReference);
NSString *uuidString = (__bridge NSString *)(stringReference);
[[NSUserDefaults standardUserDefaults] setObject:uuidString forKey:[[NSBundle mainBundle] bundleIdentifier]];
[[NSUserDefaults standardUserDefaults] synchronize];
CFRelease(uuidReference);
CFRelease(stringReference);
return uuidString;
}
}
You can use identifierForVendor after that store them to keychain and use later. Because value of keychain will not changed when re-install app.
I used to use Open UDID for this purpose. Don't know if it still works.
The serial number for Apple devices can be found under Settings -> General -> About -> Serial number.

Unique Identification of iOS device

I was using Mac address for unique identification of the iOS device, but from iOS7 the system always returns 02:00:00:00:00:00 value. I had searched three options for the mentioned issue:
Vendor identification
Advertising identification
Getting serial number using IOUnit framework
Since the IOUnitFramework is not approved by appstore, cant use it in my application. And the vendor identification and advertising identification return very long values.
Is there any other possible way to uniquely identify the ios device?
Thanks in advance
Storing a unique identifier in keychain is another option. But we can't access the keychain directly from our ios device.So is there any other alternative way for unique identification of the device?
No, Apple does not allow you to uniquely identify devices any more. This has to do with the user privacy. Since you are not identifying the user but a device.
Also don't use the ASIdentifierManager for identifying device, Apple is now reject apps that use this to identify device. The ASIdentifierManager is only to be used for advertisement purposes.
The only option left is either the the [[UIDevice currentDevice] identifierForVendor] or save your own custom create ID to the keychain.
Saving to your own create id to the keychain will make sure that if the user deletes the app en reinstalls it later you can still access this value.
You can use UDID of the device by which you can uniquely identify iPhone device
Create UIID from this method
- (NSString *)createUUID
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
[[NSUserDefaults standardUserDefaults] setObject:(__bridge NSString *)string forKey:#"UUID"];
[[NSUSerDefaults standardUserDefaults] synchronize];
return (__bridge NSString *)string;
}
Use this where you need the device UDID
- (NSString*)UUID
{
return [[NSUserDefaults standardUserDefaults] ObjectForKey:#"UUID"];
}
You might check on this link and this link. It shows you multiple ways to identify your iOS device. They are a little outdated, but identifierForVendor and advertisingIdentifier still works.
Advertising identifier is mainly used for advertising purpose, but Apple is encouraging using this identifier for any needs.
advertisingIdentifier is part of the new AdSupport.framework. The ASIdentifierManager singleton exposes the method advertisingIdentifier and calling that returns an instance of the NSUUID class.
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
Identifier for vendor also return an UUID string :
NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
There are a lot of ways for to get an unique identifier. You can get identifierForVendor as some guys recommended you or create an UUID as mokujin recommended you. Even there are external sources libraries like SecureUDID, OpenUDID... but all these has the same problem, if you remove your app and reinstall, you will get different identifier.
I have been working in a big company where they used MDM (Mobile Iron) which give you the posibility of to get the real UDID. I think you are not using MDM in your project so I recommend you to use one of the choice recommended here for me and others users and save it in your keychain. After of this, you should to check if you have this value keep in your keychain, for using it, if not, you should to get it and keep it.
Don´t save it in your NSUserDefaults because if you delete your app, your info kept there will be deleted.
For use your keychain I recommend you to use this class from Apple KeychainItemWrapper
Apple kills the way of tracking application, though we can track application using following ids
Identifier for vendor
NSUUID
CFUUID
But this device ids will reset if you factory reset your phone.
You will get detail description over here unique device identification in iOS

Is there any ways to detect the roaming status on iOS 6?

My application using below methods to detect roamming in iOS 4 and 5.
NSString *carrierPListSymLinkPath = #"/var/mobile/Library/Preferences/com.apple.carrier.plist";
NSString *operatorPListSymLinkPath = #"/var/mobile/Library/Preferences/com.apple.operator.plist";
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error = nil;
NSString *carrierPListPath = [fm destinationOfSymbolicLinkAtPath:carrierPListSymLinkPath error:&error];
NSString *operatorPListPath = [fm destinationOfSymbolicLinkAtPath:operatorPListSymLinkPath error:&error];
return (![operatorPListPath isEqualToString:carrierPListPath]);
But this code always return false on iOS6 (even i am not roaming, it always return false), i think it maybe the plist file location changed by Apple, does any one face the same issue, can anyone help me on this?
Thanks.
This is an answer I got from apple :
"Indeed. Unfortunately these files were never documented as public API and, as such, were never intended to be used by third party apps. In a lot of cases such restrictions are enforced, either technically by the iOS sandbox or administratively by App Review. However, neither of these processes is perfect, and there are occasions where apps end up doing things they shouldn't be doing. Unfortunately this puts these apps in a difficult position when the enforcement improves, as has happened in this case.
As to direct workarounds there really isn't one. The only public telephony APIs on iOS are provided by the Core Telephony framework. Its CTTelephonyNetworkInfo class gives you information about the user's 'home' cellular server, not about the network that they are roaming on."
They suggest you use geo-ip check.
Facing the same problem here since iOS6 beta 1, since that version /var/mobile/Library/Preferences/com.apple.operator.plist sym-link is no more reversable.
No other device-only way are public now, in the meanwhile the unique solution is to check for the ip via geo-ip, as Trausti Thor said, or checking for the ip class if you are developing an app for a single carrier.

CFUUIDCreate UUID changes constantly

I am a beginner iPhone app developer and I am trying to show the iPhone or App unique identifier on a label through an IBAction button. I researched a little and know that some of the code have been deprecated and CFUUID is used instead. The code below is what I used. However, every time I touch the IBAction button, the UUID changes. What am I doing wrong?
CFUUIDRef udid = CFUUIDCreate(NULL);
NSString *udidString = (NSString *) CFUUIDCreateString(NULL, udid);
uuid.text= udidString;
I think you have misunderstood the purpose of CFUUIDCreate(), Read its documentation you'll understand.
I guess the API is serving it's purpose properly, which is to create universally unique identifier means every time you call this it will return you back unique identifier randomly.
You can use
[[UIDevice currentDevice] uniqueIdentifier]
However, this method is depreciated. In order to get a unique identifier for each device, you can still use CFUUIDCreateString and save the output to user defaults. Load this value each time the app runs. If the app is deleted and then reinstalled this value will be different.
If you do need a unique identifier across app installs you can use the network MAC address.
As mentioned above, CFUUIDCreate is intended to create a different UUID each time it is run. You can create one, and store it in your app if you like, or you could try something like https://github.com/gekitz/UIDevice-with-UniqueIdentifier-for-iOS-5 - basically, it provides a uniqueGlobalDeviceIdentifier function on the UIDevice, using an MD5 hash of the MAC address as its basis.
[[UIDevice currentDevice] uniqueGlobalDeviceIdentifier]

Resources