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;
}
}
Related
I'd like to develop an app which is only available in a germany.
Preferably if a user downloads the app and leaves the germany, it should not work anymore. Is this possible?
Since i only want to know the country the user is currently i don't want to ask for the whole location.
Furthermore I'd like to restrict some content to only a specific WLAN Network. How can I do that?
Unfortunately, there is no build-in geofance on placemark level.
You could use region monitoring, but this would require to re-construct the borders of Germany as (up to 20) CLCircularRegion objects. After that, you just let the core location framework inform you if a region changes.
The drawback would be that you can only use 20 circular regions to cover the area of Germany, so you'll lose a little of precision.
A second solution would be to use a timer based check:
get the current user location
use CLGeocoder.reverseGeocodeLocation, which will provide the CLPlacemark.country
check if we are still in Germany
You can use:
NSString *countryCode = [[NSLocale currentLocale] objectForKey: NSLocaleCountryCode];
To get the user's country code. The country code for Germany is DE.
You can then check the user's country code and if it isn't DE then lock the app by bringing up a screen saying the app is locked or something like that.
For the WLAN part of your question, you can get the name of the network the user is connected to:
How to get available all wifi network name Listing in iOS using swift
This class will show only the wifi network name you are connected to -
import UIKit
import SystemConfiguration.CaptiveNetwork
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
override func viewDidLoad(){
super.viewDidLoad()
let ssid = self.getAllWiFiNameList()
print("SSID: \(ssid)")
}
func getAllWiFiNameList() -> String? {
var ssid: String?
if let interfaces = CNCopySupportedInterfaces() as NSArray? {
for interface in interfaces {
if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? {
ssid = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String
break
}
}
}
return ssid
}
}
You can check if that class is not equal to a pre-set class to block some functionality.
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
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.
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
I'm new in swift , and I'd like to see running application in the device or extract different information from the device like how many times the application was used ...
This will probably work for you or get you close to what you want.
for runningApp in NSWorkspace.sharedWorkspace().runningApplications as! [NSRunningApplication] {
if let bundleIdentifier = runningApp.bundleIdentifier {
NSLog(bundleIdentifier)
}
if let launchDate = runningApp.launchDate {
NSLog(launchDate.description)
}
}