iOS get current wlan network name - iphone

I am looking for a way to obtain information (at least the name) of the current connected wlan network in objective-c for iOS5.
I need this because we are currently developing an application that do not work in a particular network. In this network (on our university) the port is closed that we need to connect to the server. But there is another network also available and we want to tell the user that he has to switch the network if he is connected to the aforementioned one.
I do not even know where to start. Does anyone have an idea or any hints?
Thanks and regards

From iOS >= 4.1 it's possible to obtain SSID of wireless network that device is currenctly connected to.
For this you'd use function CNCopyCurrentNetworkInfo
Details on implemenation are available on SO: iPhone get SSID without private library

It is possible to get the current wifi information from the Captive Network. In the past, apple actually disabled this for a while, but they seems to re-enabled it due to strong request. It is also possible that they decide to close this in the future.
The information we can get is BSSID, SSID, SSIDDATA. BSSID is the unique address for wifi, SSID is the current wifi name, SSIDDATA is the hex representation for the SSID.
For Swift 3.1:
func printCurrentWifiInfo() {
if let interface = CNCopySupportedInterfaces() {
for i in 0..<CFArrayGetCount(interface) {
let interfaceName: UnsafeRawPointer = CFArrayGetValueAtIndex(interface, i)
let rec = unsafeBitCast(interfaceName, to: AnyObject.self)
if let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)" as CFString), let interfaceData = unsafeInterfaceData as? [String : AnyObject] {
// connected wifi
print("BSSID: \(interfaceData["BSSID"]), SSID: \(interfaceData["SSID"]), SSIDDATA: \(interfaceData["SSIDDATA"])")
} else {
// not connected wifi
}
}
}
}
For Objective-C
NSArray *interFaceNames = (__bridge_transfer id)CNCopySupportedInterfaces();
for (NSString *name in interFaceNames) {
NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)name);
NSLog[#"wifi info: bssid: %#, ssid:%#, ssidData: %#", info[#"BSSID"], info[#"SSID"], info[#"SSIDDATA"]];
}

As of iOS 12, you'll need to allow Wifi Information access in the capabilities.
From Apple:
To use this function in iOS 12 and later, enable the Access WiFi Information capability for your app in Xcode. When you enable this capability, Xcode automatically adds the Access WiFi Information entitlement to your entitlements file and App ID.

Related

BLE iOS - Failed to encrypt the connection, the connection has timed out unexpectedly

I'm using #capacitor-community/bluetooth-le to connect my Ionic 6 APP to a specific BLE device.
In Android everything works fine.
In iOS, first time connects to BLE successfully but next times (after pairing) gives the following error when try to connects: "Failed to encrypt the connection, the connection has timed out unexpectedly."
I have been tried a lot of different approachs: connects after scan. Connects when is scanning. But nothing works. What is strange is in first time everything works fine (after pairing).
Any help?
Unfortunately this is kind of a known issue in iOS. What I think is happening is that because you have already paired/bonded with the device at the OS level, the connection is being re-established at the OS level when the remote BLE device is discoverable. When you are attempting to reconnect to the remote device from your app, a connection is already in place at the OS level which is why it is failing at the app level. Alternatively, maybe the stored keys from the bonding process is causing the rebonding/pairing process to clash. You can confirm the issue by doing the following:-
Go to the iOS settings, Bluetooth, then unpair the device if it exists.
Attempt to reconnect to the device from your iOS app.
Disconnect the device from your iOS app (do not unpair from the Bluetooth settings this time).
Try to connect to the remote device from your Android app (or any other device that you can use apart from the iOS device). If the connection doesn't succeed, it means that the iOS device is still connected to the remote device.
If the connection succeeds from the Android device, try to disconnect and reconnect from the iOS device. If the connection succeeds, you'll know that the issue is with the OS level connection, and if the connection doesn't succeed, you'll know that the issue is with the stored bonding/pairing keys clashing.
As for the solution, I don't think there's a simple and straight-forward one unfortunately. Below is one suggested solution which I found useful in the past (you may need to modify this for your ionic app):-
In some cases, like for HID devices, once a peripheral is bonded, iOS
will automatically connect to it whenever it sees the peripheral
advertising. This behavior occurs independently of any app, and a
peripheral can be connected to an iOS device, but not connected to the
app that originally established the bond. If a bonded peripheral
disconnects from an iOS device and then reconnects at the iOS level,
the app will need to retrieve the peripheral object
(retrieveConnectedPeripherals(with[Services/Identifiers]:) and
explicitly connect again through a CBCentralManager to establish an
app-level connection. To retrieve your device with this method, you
must specify either the Apple-assigned device identifier from the
previously-returned CBPeripheral object or at least one service it
contains.
iOS does not allow developer apps to clear a peripheral’s bonding
status from the cache. To clear a bond, the user must go to the
Bluetooth section of iOS Settings and explicitly “Forget” the
peripheral. It may be helpful to include this information in your
app’s UI if it’ll affect user experience, as most users will not know
this.
You can find more information about this in the links below:-
The ultimate guide to Apple's CoreBluetooth
CoreBluetooth iOS pairing issue
CoreBluetooth pairing/forgetting
Unable to reconnect after cancelling BLE peripheral
In my case after iPhone pairs with peripheral, never connects anymore. What is strange, in my iPhone 6s with iOS 15.5 everythings works fine.
The pugin has this code (it's possible to some is wrong?)
https://github.com/capacitor-community/bluetooth-le/blob/main/ios/Plugin/Plugin.swift
let CONNECTION_TIMEOUT: Double = 10
let DEFAULT_TIMEOUT: Double = 5
#objc func connect(_ call: CAPPluginCall) {
guard self.getDeviceManager(call) != nil else { return }
guard let device = self.getDevice(call, checkConnection: false) else { return }
let timeout = self.getTimeout(call, defaultTimeout: CONNECTION_TIMEOUT)
device.setOnConnected(timeout, {(success, message) -> Void in
if success {
// only resolve after service discovery
call.resolve()
} else {
call.reject(message)
}
})
self.deviceManager?.setOnDisconnected(device, {(_, _) -> Void in
let key = "disconnected|\(device.getId())"
self.notifyListeners(key, data: nil)
})
self.deviceManager?.connect(device, timeout, {(success, message) -> Void in
if success {
log("Connected to peripheral. Waiting for service discovery.")
} else {
call.reject(message)
}
})
}
I already tried another plugins, and the result is the same.

Getting iPhone Carrier Mobile Number in Xcode [duplicate]

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

Can you pass WiFi settings from an iOS device to an ExternalAccessory object?

I've heard that iOS 5 introduced a feature in which the iOS device can share its wifi configuration with a docked accessory via the ExternalAccessory framework. The trouble is that I can't find any specific details on implementing this type of scheme in the SDK docs.
From my research, I've begun to suspect it's achieved via the 'iPhone Configuration Utility' but this still seems like a bit of a messy method to implement on a device.
Anyone got any ideas?
Once the wifi setup data is available, it should be easy enough to package it up and send it out via the ExternalAccessory framework to the device, where I'll build in protocol support accordingly.
Thanks
Yes! you certainly can. However, to use HomeKit (the library you need) you first need to be a certified MFi (Made For iDevice-iPhone-iPod-iPad) developer. This gives you the ability to allow a user to view all available wifi networks and choose to link the device.
One example of this is Withings with their Aura sleep aid. See screenshot from on boarding experience:
Then the user can then choose to share their home wifi information securely with the new device.
The user-visible UI looks like this:
http://www.theregister.co.uk/2012/07/12/pure_contour_200i_air_airplay_wireless_music_system/
https://withings.zendesk.com/hc/en-us/articles/201488707-Wi-Fi-Setup-of-the-Wireless-Scale-WS-30
A bit late but configureAccessory is the method (part of ExternalAccessory) introduced in iOS 8.0 that you can use to configure a wifi accessory:
https://developer.apple.com/documentation/externalaccessory/eawifiunconfiguredaccessorybrowser/1613907-configureaccessory
It's part of the EAWiFiUnconfiguredAccessoryBrowser class:
https://developer.apple.com/documentation/externalaccessory/eawifiunconfiguredaccessorybrowser
And showBluetoothAccessoryPicker is the one for Bluetooth products:
https://developer.apple.com/documentation/externalaccessory/eaaccessorymanager/1613913-showbluetoothaccessorypicker
which is part of the EAAccessoryManager class:
https://developer.apple.com/documentation/externalaccessory/eaaccessorymanager
I doubt Apple would ever allow for an average developer to access private data such as wifi connections settings. Maybe trusted third party accessory provider yes, but you probably no.
Wifi settings are private and contain passwords. An average (non-power) user uses more or less the same/similar password for everything including their Wifi network. If an app can easily read that it could be badly exploited.
The same way you cannot get the Apple id let alone the password.
Have you seen this: iPhone get SSID without private library
Is prompting the App user for a secured network password out of the question?
You can at least get the SSID of an unsecured network and pass it to your accessory with a getter something like:
#import <SystemConfiguration/CaptiveNetwork.h>
#implementation DeviceWifiSSID
//https://stackoverflow.com/a/5198968/614688
+(NSString *)deviceSSID
{
NSArray *ifs = (__bridge id)CNCopySupportedInterfaces();
id info = nil;
for (NSString *ifnam in ifs) {
info = (__bridge id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
if ([info objectForKey:#"SSID"] != nil)
{
return [info objectForKey:#"SSID"];
}
}
return nil;
}
#end

Can you access an iPhone's phone number via code in an app? [duplicate]

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

On the iPhone, is it possible to find out which WIFI network we are connected to?

If yes, can we also get additional information about the network configuration?
One useful way to do this could be getting the SSID of the current network. Is there an API to do that?
Update: I found a similar question here:
Can the iPhone SDK obtain the Wi-Fi SSID currently connected to?
Try following method:
#import <SystemConfiguration/CaptiveNetwork.h>
NSString *wifiName = #"Not Found";
CFArrayRef myArray = CNCopySupportedInterfaces();
if (myArray != nil) {
CFDictionaryRef myDict = CNCopyCurrentNetworkInfo(CFArrayGetValueAtIndex(myArray, 0));
if (myDict != nil) {
NSDictionary *dict = (NSDictionary*)CFBridgingRelease(myDict);
wifiName = [dict valueForKey:#"SSID"];
}
}
NSLog(#"wifiName:%#", wifiName);
(Separate answer to preserve history etc.)
It looks like you might not be able to determine the SSID of the WLAN to which you're connected, at least in an app that will go into the App Store. These people use a private API - Preferences.framework - to get to the details of the WLAN (like "is it hidden?" "What's the name?" etc.).
Can't comment, but this might be a duplicate:
Accessing iPhone WiFi Information via SDK
Answer seems to be no. I've done my own research on this and have been unable to find a supported way of getting the SSID.
Have you looked at the Reachability sample app?
Edit: The Reachability app demonstrates the use of the SystemConfiguration framework to show whether your phone's connected to the internet and, if so, how.
It further allows you to distinguish between a local WiFi connection and not (+[Reachability reachabilityForLocalWiFi]).
Regarding the meat of your question, you'll have to consult the phone's ARP table. This answer shows you how to do just that.