How to get all previously connected Wi-Fi networks in Swift? - ios

I know it's not possible to get all available Wi-Fi networks and it's possible to get the information of current connected Wi-Fi network, correct me if I'm wrong.
I just want to know the feasibility of getting the information of all previously connected Wi-Fi networks, Please help me by sharing your experience.
FYI,
I'm using the following code get current connected Wi-Fi network's info and it's working fine.
var currentSSID: String!
let interfaces:CFArray! = CNCopySupportedInterfaces()
for i in 0..<CFArrayGetCount(interfaces) {
let interfaceName: UnsafePointer<Void>
= CFArrayGetValueAtIndex(interfaces, i)
let rec = unsafeBitCast(interfaceName, AnyObject.self)
let unsafeInterfaceData = CNCopyCurrentNetworkInfo("\(rec)")
if unsafeInterfaceData != nil {
let interfaceData = unsafeInterfaceData! as Dictionary!
currentSSID = interfaceData["SSID"] as! String
} else {
currentSSID = ""
}
print(currentSSID)
}

From a stock iPhone this is not possible from the settings. The information that you want is stored in the iPhone's keychain. If you have access to the iPhone SDK you can start messing around if you like, but I will leave it at that since that would be a StackOverflow answer. Source
If you have ICloud Keychain enabled, it is possible to fetch this data. Otherwise, you can't. Source You can use kishikawakatsumi/KeychainAccess or do it yourself. Here is homemade code to save and retrieve keychain values.
It is a simple swift wrapper for Keychain that works on iOS and OS X

Related

How to identify if an iOS apps is connected to a specific WiFi network?

I am developing a React Native apps to automatically clock in/out users when they near office.
I intend to use WiFi as a method to verify if user is at the location or not. MAC address should be a unique and fixed identifier that can verify if user is here.
If using SSID / wifi network name, user can just alter theirs at home to match the office one.
From here, it seems like it's not feasible anymore? How can I programmatically get the MAC address of an iphone
If it's impossible to get MAC address from apps in iOS due to security concern, is there any way I can achieve this? To correctly identify a specific wifi network it's connected to?
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
}
}
}
P.S. I took that from iOS get current wlan network name

iOS MapKit Get Places information and Reviews

I'm using mapkit and able to get Address for a particular location
let firstPlacemark = placemarks,
let addressDictionary = firstPlacemark.addressDictionary else { return }
// let street = addressDictionary["Street"]
// let city = addressDictionary["City"]
// let state = addressDictionary["State"]
// let zip = addressDictionary["ZIP"]
print(addressDictionary.description)
if let array = addressDictionary["FormattedAddressLines"] as? [Any] {
let address = array.map { "\($0)" }.joined(separator: ",\n")
print("Address : \(address)")
}
But Can we get more information like reviews contact no. images etc. Like Apple Maps shows (Observe Screeenshot)
Is there any API available in iOS for this or it will be provided via TripAdvisor???
P.S: I don't want to Any Google API.
Dear down voters if don't know the answers then kindly don't waste my points. It's easy to downvote, but you never know how much efforts has been added to earn those points.
OR Kindly provide me solution or show me if question is duplicate.
You can use Tripadvisor API
https://developer-tripadvisor.com/content-api/documentation/
ex.
http://api.tripadvisor.com/api/partner/2.0/location/155507?key=YOURKEY

Will deviceid saved in iOS keychain be synced across all devices using same iCloud account?

I wanted to have same device id for the device even after re-installing the app. I was planning to save it to keychain and retrieve it every time.
I want to know if keychain data will get synced across all the devices using the same iCloud email id.
I am using the keychainwrapper in this downloadable_link.
This is what I ended up doing.
I read that the same UUID will be shared across all devices with same iCloud account.(Not sure about this.)
I had to restrict app login for upto 3 devices for each email id. If keychain data will get synced, then I cannot do this . If I have 3 different iPhones, it will be considered as a single device only if the user uses same icloud account.
After some googleing I came across SAMKeychain.
It has a property called synchronizationmode which I think will do the job of preventing the keychain key /value from syncing it to iCloud.
I use the below code to generate UUID.
func UUID() -> String {
let bundleName = Bundle.main.infoDictionary!["CFBundleName"] as! String
let accountName = Bundle.main.bundleIdentifier! + String(Bundle.main.bundleIdentifier!.characters.reversed()) // just one extra layer of protection.. :p
var applicationUUID = SAMKeychain.password(forService: bundleName, account: accountName)
if applicationUUID == nil {
applicationUUID = (UIDevice.current.identifierForVendor?.uuidString)!
// Save applicationUUID in keychain without synchronization
let query = SAMKeychainQuery()
query.service = bundleName
query.account = accountName
query.password = applicationUUID
query.synchronizationMode = SAMKeychainQuerySynchronizationMode.no
do {
try query.save()
} catch let error as NSError {
print("SAMKeychainQuery Exception: \(error)")
}
}
return applicationUUID!
}
You can check the sample app in swift 3 here in GITHUB.If someone has a better answer , Please let me know.
NOTE: SAMKeychain from their official github page was not working properly for me. Please use the one I am using in the UniqueUUIDAPP. I had to make some code commenting to make it work.

How to detect First launch of app on every new version upgrade?

I have a requirement of detecting the first launch of app after the user upgrades the app to a newer version. I need to perform certain task only on first launch of app after the user upgrades the app to a new version. Many links available online but none answer clearly to my query. How to achieve this in Swift 2 , iOS 9.
Most of the answers available says to maintain a key in NSUserDefaults and set its value to false and after first launch make it true. But the problem is after I upgrade my app the variable still will be true and thus my scenario fails on app upgrade. Any help would be much appreciated. Thanks!
Try this:
let existingVersion = NSUserDefaults.standardUserDefaults().objectForKey("CurrentVersionNumber") as? String
let appVersionNumber = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String
if existingVersion != appVersionNumber {
NSUserDefaults.standardUserDefaults().setObject(appVersionNumber, forKey: "CurrentVersionNumber")
NSUserDefaults.standardUserDefaults().synchronize()
//You can handle your code here
}
updating Yogesh's perfect, yet simple solution to swift 4
let existingVersion = UserDefaults.standard.object(forKey: "CurrentVersionNumber") as? String
let appVersionNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
if existingVersion != appVersionNumber {
print("existingVersion = \(String(describing: existingVersion))")
UserDefaults.standard.set(appVersionNumber, forKey: "CurrentVersionNumber")
// run code here.
}

iPhone get a list of all SSIDs without private library

Is it possible the get a list of all available SSIDs on the iPhone without using a private library?
I read iPhone get SSID without private library which is about getting details about the current network.
This answer mentions:
If you jailbreak your device you can use the Apple80211 private framework to look up the available Wi-Fi networks and their signal strength. But that also means your app will get rejected.
Apple has the CaptiveNetwork API but there doesn't seem to be a solution to get a list of all available networks. It seems it's only possible to do so with using the Apple80211 private library, or connecting to all of them.
Am I missing something, or is there no solution?
Without the use of private library (Apple80211) you can only get the SSID of the network your device is currently connected to.
Since iOS 9, you can use NEHotspotHelper to get a list of SSIDs. But you have to get the com.apple.developer.networking.HotspotHelper entitlement from Apple by sending a request.
Check https://developer.apple.com/documentation/networkextension/nehotspothelper for more infomation.
Some new APIs have been released as part of the Network Extension in iOS 9 and iOS 11. While neither allows you to scan for networks while your app is running, they both allow you to do related tasks. E.g. you can scan for networks while the Settings Wi-Fi page is running using Hotspot Helper, and you can make it easier for a user to join a network using either of these.
Here's a comparison of the two frameworks.
Hotspot Helper
NEHotspotHelper (introduced in iOS 9, WWDC 2015).
Requires special permission from Apple.
Requires the com.apple.developer.networking.HotspotHelper entitlement.
For step-by-step instructions to get this working, see this answer.
Allows you to participate in the discovery/authentication to a Wi-Fi network via the Wi-Fi screen in the Settings app. You register to be notified when networks are being scanned (e.g. when the user launches Wi-Fi in the Settings app), and you can automatically pre-fill the password and display an annotation near the network name. The user still needs to tap on the network name to connect, but it won't prompt for a password if you pre-filled it.
Hotspot Configuration
NEHotspotConfigurationManager (introduced in iOS 11, WWDC 2017).
Does not require special permission from Apple.
Requires the com.apple.developer.networking.HotspotConfiguration entitlement.
Allows you to initiate a connection to a Wi-Fi network. You give it a list of SSIDs/Passwords that should be connected to while your app is running. It will present a dialog asking the user if they want to connect to the network.
Step 1: add the framework SystemConfiguration.framework
Step 2: import following header file
import SystemConfiguration
import SystemConfiguration.CaptiveNetwork
Step 3: Now Use Code:
func getUsedSSID()->String {
let interfaces = CNCopySupportedInterfaces()
if interfaces != nil {
let interfacesArray = CFBridgingRetain(interfaces) as! NSArray
if interfacesArray.count > 0 {
let interfaceName = interfacesArray[0] as! String
let unsafeInterfaceData = CNCopyCurrentNetworkInfo(interfaceName)! as Dictionary
let SSIDName = unsafeInterfaceData["SSID"] as! String
print(SSIDName)/* here print recentally used wifi name*/
return SSIDName
}else{
return "0"
}
}else{
return "0"
}
}
First of All import above two system Header file
import SystemConfiguration/SystemConfiguration.h
import SystemConfiguration/CaptiveNetwork.h
below Function/Method Return SSIDName
-(NSString *)getNetworkId{
NSString *string = CFBridgingRelease(CNCopySupportedInterfaces());
NSArray *interfacesArray = CFBridgingRelease(CFBridgingRetain(string));
if(interfacesArray.count > 0){
NSString *networkName = [interfacesArray objectAtIndex:0];
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)networkName;
NSDictionary *unsafeInterfaceData = CFBridgingRelease(CNCopyCurrentNetworkInfo(yourFriendlyCFString));
NSString *ssidName = unsafeInterfaceData[#"SSID"];
return ssidName;
}
return #"No network Found";
}
#import SystemConfiguration#
##import SystemConfiguration.CaptiveNetwork##
//create variable
var SSIDNameArray = NSMutableArray()
var nameArray : NSArray = [];
// Here function to return all SSIDName
func getUsedSSID()->NSArray{
let interfaces = CNCopySupportedInterfaces()
if interfaces != nil {
let interfacesArray = CFBridgingRetain(interfaces) as! NSArray
if interfacesArray.count > 0 {
for interfaceName in interfacesArray {
let unsafeInterfaceData = CNCopyCurrentNetworkInfo(interfaceName as! CFString)! as NSDictionary
let SSIDName = unsafeInterfaceData["SSID"] as! String
self.SSIDNameArray .add(SSIDName)
}
nameArray = self.SSIDNameArray .copy() as! NSArray
return nameArray;
}else{
return nameArray;
}
}else{
return nameArray;
}
}

Resources