iPhone get SSID without private library - ios
I have a commercial app that has a completely legitimate reason to see the SSID of the network it is connected to: If it is connected to a Adhoc network for a 3rd party hardware device it needs to be functioning in a different manner than if it is connected to the internet.
Everything I've seen about getting the SSID tells me I have to use Apple80211, which I understand is a private library. I also read that if I use a private library Apple will not approve the app.
Am I stuck between an Apple and a hard place, or is there something I'm missing here?
As of iOS 7 or 8, you can do this (need Entitlement for iOS 12+ as shown below):
#import SystemConfiguration.CaptiveNetwork;
/** Returns first non-empty SSID network info dictionary.
* #see CNCopyCurrentNetworkInfo */
- (NSDictionary *)fetchSSIDInfo {
NSArray *interfaceNames = CFBridgingRelease(CNCopySupportedInterfaces());
NSLog(#"%s: Supported interfaces: %#", __func__, interfaceNames);
NSDictionary *SSIDInfo;
for (NSString *interfaceName in interfaceNames) {
SSIDInfo = CFBridgingRelease(
CNCopyCurrentNetworkInfo((__bridge CFStringRef)interfaceName));
NSLog(#"%s: %# => %#", __func__, interfaceName, SSIDInfo);
BOOL isNotEmpty = (SSIDInfo.count > 0);
if (isNotEmpty) {
break;
}
}
return SSIDInfo;
}
Example output:
2011-03-04 15:32:00.669 ShowSSID[4857:307] -[ShowSSIDAppDelegate fetchSSIDInfo]: Supported interfaces: (
en0
)
2011-03-04 15:32:00.693 ShowSSID[4857:307] -[ShowSSIDAppDelegate fetchSSIDInfo]: en0 => {
BSSID = "ca:fe:ca:fe:ca:fe";
SSID = XXXX;
SSIDDATA = <01234567 01234567 01234567>;
}
Note that no ifs are supported on the simulator. Test on your device.
iOS 12
You must enable access wifi info from capabilities.
Important
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. Documentation link
Swift 4.2
func getConnectedWifiInfo() -> [AnyHashable: Any]? {
if let ifs = CFBridgingRetain( CNCopySupportedInterfaces()) as? [String],
let ifName = ifs.first as CFString?,
let info = CFBridgingRetain( CNCopyCurrentNetworkInfo((ifName))) as? [AnyHashable: Any] {
return info
}
return nil
}
UPDATE FOR iOS 10 and up
CNCopySupportedInterfaces is no longer deprecated in iOS 10. (API Reference)
You need to import SystemConfiguration/CaptiveNetwork.h and add SystemConfiguration.framework to your target's Linked Libraries (under build phases).
Here is a code snippet in swift (RikiRiocma's Answer):
import Foundation
import SystemConfiguration.CaptiveNetwork
public class SSID {
class func fetchSSIDInfo() -> String {
var currentSSID = ""
if let interfaces = 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
}
}
}
return currentSSID
}
}
(Important: CNCopySupportedInterfaces returns nil on simulator.)
For Objective-c, see Esad's answer here and below
+ (NSString *)GetCurrentWifiHotSpotName {
NSString *wifiName = nil;
NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
for (NSString *ifnam in ifs) {
NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
if (info[#"SSID"]) {
wifiName = info[#"SSID"];
}
}
return wifiName;
}
UPDATE FOR iOS 9
As of iOS 9 Captive Network is deprecated*. (source)
*No longer deprecated in iOS 10, see above.
It's recommended you use NEHotspotHelper (source)
You will need to email apple at networkextension#apple.com and request entitlements. (source)
Sample Code (Not my code. See Pablo A's answer):
for(NEHotspotNetwork *hotspotNetwork in [NEHotspotHelper supportedNetworkInterfaces]) {
NSString *ssid = hotspotNetwork.SSID;
NSString *bssid = hotspotNetwork.BSSID;
BOOL secure = hotspotNetwork.secure;
BOOL autoJoined = hotspotNetwork.autoJoined;
double signalStrength = hotspotNetwork.signalStrength;
}
Side note: Yup, they deprecated CNCopySupportedInterfaces in iOS 9 and reversed their position in iOS 10. I spoke with an Apple networking engineer and the reversal came after so many people filed Radars and spoke out about the issue on the Apple Developer forums.
Here's the cleaned up ARC version, based on #elsurudo's code:
- (id)fetchSSIDInfo {
NSArray *ifs = (__bridge_transfer NSArray *)CNCopySupportedInterfaces();
NSLog(#"Supported interfaces: %#", ifs);
NSDictionary *info;
for (NSString *ifnam in ifs) {
info = (__bridge_transfer NSDictionary *)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
NSLog(#"%# => %#", ifnam, info);
if (info && [info count]) { break; }
}
return info;
}
This works for me on the device (not simulator). Make sure you add the systemconfiguration framework.
#import <SystemConfiguration/CaptiveNetwork.h>
+ (NSString *)currentWifiSSID {
// Does not work on the simulator.
NSString *ssid = nil;
NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
for (NSString *ifnam in ifs) {
NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
if (info[#"SSID"]) {
ssid = info[#"SSID"];
}
}
return ssid;
}
This code work well in order to get SSID.
#import <SystemConfiguration/CaptiveNetwork.h>
#implementation IODAppDelegate
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
CFArrayRef myArray = CNCopySupportedInterfaces();
CFDictionaryRef myDict = CNCopyCurrentNetworkInfo(CFArrayGetValueAtIndex(myArray, 0));
NSLog(#"Connected at:%#",myDict);
NSDictionary *myDictionary = (__bridge_transfer NSDictionary*)myDict;
NSString * BSSID = [myDictionary objectForKey:#"BSSID"];
NSLog(#"bssid is %#",BSSID);
// Override point for customization after application launch.
return YES;
}
And this is the results :
Connected at:{
BSSID = 0;
SSID = "Eqra'aOrange";
SSIDDATA = <45717261 27614f72 616e6765>;
}
If you are running iOS 12 you will need to do an extra step.
I've been struggling to make this code work and finally found this on Apple's site:
"Important
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."
https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo
See CNCopyCurrentNetworkInfo in CaptiveNetwork: http://developer.apple.com/library/ios/#documentation/SystemConfiguration/Reference/CaptiveNetworkRef/Reference/reference.html.
Here's the short & sweet Swift version.
Remember to link and import the Framework:
import UIKit
import SystemConfiguration.CaptiveNetwork
Define the method:
func fetchSSIDInfo() -> CFDictionary? {
if let
ifs = CNCopySupportedInterfaces().takeUnretainedValue() as? [String],
ifName = ifs.first,
info = CNCopyCurrentNetworkInfo((ifName as CFStringRef))
{
return info.takeUnretainedValue()
}
return nil
}
Call the method when you need it:
if let
ssidInfo = fetchSSIDInfo() as? [String:AnyObject],
ssID = ssidInfo["SSID"] as? String
{
println("SSID: \(ssID)")
} else {
println("SSID not found")
}
As mentioned elsewhere, this only works on your iDevice. When not on WiFi, the method will return nil – hence the optional.
For iOS 13
As from iOS 13 your app also needs Core Location access in order to use the CNCopyCurrentNetworkInfo function unless it configured the current network or has VPN configurations:
So this is what you need (see apple documentation):
- Link the CoreLocation.framework library
- Add location-services as a UIRequiredDeviceCapabilities Key/Value in Info.plist
- Add a NSLocationWhenInUseUsageDescription Key/Value in Info.plist describing why your app requires Core Location
- Add the "Access WiFi Information" entitlement for your app
Now as an Objective-C example, first check if location access has been accepted before reading the network info using CNCopyCurrentNetworkInfo:
- (void)fetchSSIDInfo {
NSString *ssid = NSLocalizedString(#"not_found", nil);
if (#available(iOS 13.0, *)) {
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
NSLog(#"User has explicitly denied authorization for this application, or location services are disabled in Settings.");
} else {
CLLocationManager* cllocation = [[CLLocationManager alloc] init];
if(![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){
[cllocation requestWhenInUseAuthorization];
usleep(500);
return [self fetchSSIDInfo];
}
}
}
NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
id info = nil;
for (NSString *ifnam in ifs) {
info = (__bridge_transfer id)CNCopyCurrentNetworkInfo(
(__bridge CFStringRef)ifnam);
NSDictionary *infoDict = (NSDictionary *)info;
for (NSString *key in infoDict.allKeys) {
if ([key isEqualToString:#"SSID"]) {
ssid = [infoDict objectForKey:key];
}
}
}
...
...
}
Related
application crash on ios 11 when working with AddressBook framework?
I'm working on voip app. fetch contact work but when I want to make call, app crash. [ABSAddressBook contacts]: message sent to deallocated instance 0x1c1478180 warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available. crash happen in this line. NSArray *lContacts = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); - (void) checkContactListForJogvoiceList { // if (![BundleLocalData isLoadingJogvoiceContactList]) { // [BundleLocalData setLoadingJogvoiceContactList:true]; int maxPhoneNumberSubmit = 200; NSArray *lContacts = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); NSMutableDictionary *phoneNumberContactsDictionary = [[NSMutableDictionary alloc] init]; NSMutableArray *allPhoneNumberList = [[NSMutableArray alloc] init]; for (id lPerson in lContacts) { ABRecordRef person = (ABRecordRef)lPerson; NSArray *phoneList = [AppUtil getContactPhoneList:person]; for (NSString* phoneNumber in phoneList) { NSMutableArray* contactList = phoneNumberContactsDictionary[phoneNumber]; if (!contactList) { contactList = [[NSMutableArray alloc] init]; } [contactList addObject:(__bridge ABRecordRef)person]; phoneNumberContactsDictionary[phoneNumber] = contactList; } [allPhoneNumberList addObjectsFromArray:phoneList]; if (allPhoneNumberList.count >= maxPhoneNumberSubmit) { [self checkContactList:allPhoneNumberList phoneNumberContactsDictionary:phoneNumberContactsDictionary]; } } if (allPhoneNumberList.count > 0) { [self checkContactList:allPhoneNumberList phoneNumberContactsDictionary:phoneNumberContactsDictionary]; } // ABAddressBookUnregisterExternalChangeCallback(addressBook, sync_address_book, self); // [BundleLocalData setLoadingJogvoiceContactList:false]; // } } probably because AddressBook framework deprecate in ios9? am I right? I don’t want to use Contacts framework.
According to Apple doc ABAddressBookCreateWithOptions using address book function ABAddressBookCreateWithOptions returns NULL if no permission granted from user. On iOS 6.0 and later, if the caller does not have access to the Address Book database: For apps linked against iOS 6.0 and later, this function returns NULL. For apps linked against previous version of iOS, this function returns an empty read-only database. You should follow this article How do I correctly use ABAddressBookCreateWithOptions method in iOS 6?
Detect if Secure Enclave is available on current device
Is there a certain way to detect if storing in Secure Enclave is available on current device?
Here is another solution: Device.h #import <Foundation/Foundation.h> #interface Device : NSObject +(BOOL) hasSecureEnclave; +(BOOL) isSimulator; +(BOOL) hasBiometrics; #end Device.m #import "Device.h" #import <LocalAuthentication/LocalAuthentication.h> #implementation Device //To check that device has secure enclave or not +(BOOL) hasSecureEnclave { NSLog(#"IS Simulator : %d", [Device isSimulator]); return [Device hasBiometrics] && ![Device isSimulator] ; } //To Check that this is this simulator +(BOOL) isSimulator { return TARGET_OS_SIMULATOR == 1; } //Check that this device has Biometrics features available +(BOOL) hasBiometrics { //Local Authentication Context LAContext *localAuthContext = [[LAContext alloc] init]; NSError *error = nil; /// Policies can have certain requirements which, when not satisfied, would always cause /// the policy evaluation to fail - e.g. a passcode set, a fingerprint /// enrolled with Touch ID or a face set up with Face ID. This method allows easy checking /// for such conditions. BOOL isValidPolicy = [localAuthContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]; if (isValidPolicy) { if (#available(ios 11.0, *)){ if (error.code != kLAErrorBiometryNotAvailable){ isValidPolicy = true; } else{ isValidPolicy = false; } }else{ if (error.code != kLAErrorTouchIDNotAvailable){ isValidPolicy = true; }else{ isValidPolicy = false; } } return isValidPolicy; } return isValidPolicy; } #end If you want solution in Swift 4, then refer this link. Solution in Swift 4
For a developer, there is exactly one thing the Secure Enclave can do: Create and hold private keys for elliptic curve cryptography, and encrypt or decrypt data using these keys. On iOS 9, the attributes describing elliptic curve algorithms are not there - therefore, if you are running iOS 9, then you can assume the Secure Enclave is not there, because you cannot use it. On iOS 10 and above, there is just one way to decide guaranteed correctly if the Secure Enclave is present: Create an elliptic curve encryption key in the Secure Enclave, as described by Apple's documentation. If this fails, and the error has a code of -4 = errSecUnimplemented, then there is no Secure Enclave. If you insist on checking a list of devices, you only need the devices that are documented as having no Secure Enclave but are able to run iOS 10, because on iOS 9 it is never available.
I did it myself: + (BOOL) isDeviceOkForSecureEnclave { double OSVersionNumber = floor(NSFoundationVersionNumber); UIUserInterfaceIdiom deviceType = [[UIDevice currentDevice] userInterfaceIdiom]; BOOL isOSForSecureEnclave = OSVersionNumber > NSFoundationVersionNumber_iOS_8_4 ? YES:NO; //iOS 9 and up are ready for SE BOOL isDeviceModelForSecureEnclave = NO; switch (deviceType) { case UIUserInterfaceIdiomPhone: //iPhone isDeviceModelForSecureEnclave = [self isPhoneForSE]; break; case UIUserInterfaceIdiomPad: //iPad isDeviceModelForSecureEnclave = [self isPadForSE]; break; default: isDeviceModelForSecureEnclave = false; break; } return (isOSForSecureEnclave && isDeviceModelForSecureEnclave) ? YES:NO; } /** The arrays are models that we know not having SE in hardware, so if the current device is on the list it means it dosent have SE */ + (BOOL) isPhoneForSE { NSString *thisPlatform = [self platform]; NSArray * oldModels = [NSArray arrayWithObjects: #"x86_64", #"iPhone1,1", #"iPhone1,2", #"iPhone2,1", #"iPhone3,1", #"iPhone3,3", #"iPhone4,1", #"iPhone5,1", #"iPhone5,2", #"iPhone5,3", #"iPhone5,4", nil]; BOOL isInList = [oldModels containsObject: thisPlatform]; return !isInList; } + (BOOL) isPadForSE { //iPad Mini 2 is the earliest with SE // "iPad4,4" NSString *thisPlatform = [self platform]; NSArray * oldModels = [NSArray arrayWithObjects: #"x86_64", #"#iPad", #"#iPad1,0", #"#iPad1,1", #"iPad2,1", #"iPad2,2", #"iPad2,3", #"iPad2,4", #"iPad2,5", #"iPad2,6", #"iPad2,7", #"iPad3,1", #"iPad3,2", #"iPad3,3", #"iPad3,4", #"iPad3,5", #"iPad3,6",nil]; BOOL isInList = [oldModels containsObject: thisPlatform]; return !isInList; } + (NSString *)platform { size_t size; sysctlbyname("hw.machine", NULL, &size, NULL, 0); char *machine = malloc(size); sysctlbyname("hw.machine", machine, &size, NULL, 0); NSString *platform = [NSString stringWithUTF8String:machine]; free(machine); return platform; } #end
There is a more straightforward way to check if Secure Enclave is available using the CryptoKit framework. The following approach is iOS 13+ and Swift only. import CryptoKit if TARGET_OS_SIMULATOR == 0 && SecureEnclave.isAvailable { // use Secure Enclave } Additional check for Simulator is needed since SecureEnclave.isAvailable returns true running on a Simulator (checked on iOS 14.4).
Address Book UI Framework deprecated methods
I am working on an existing objective c project , While reading Address Book UI Framework Reference for iOS i found the below classes have deprecated in iOS 9 . ( ABUnknownPersonViewController , ABPersonViewController , ABPeoplePickerNavigationController, ABNewPersonViewController ) What is the replacement of this .? Where i can find some document related this . any help appreciated . Thanks in advance .
The AddressBookUI framework has been deprecated in iOS 9, so better you should use ContactsUI Framework. It has many new features including all the features of AddressBookUI framework. So, in case if you are targeting the iOS 9 specifically then you should go for ContactsUI Framework. To check that AddressBookUI framework is available for specific iOS version you can do the following: if ([CNContactStore class]) { CNContactStore *store = [CNContactStore new]; //... } else { // Fallback to old framework } Here is the complete code for that: - (void) contactScan { if ([CNContactStore class]) { //ios9 or later CNEntityType entityType = CNEntityTypeContacts; if( [CNContactStore authorizationStatusForEntityType:entityType] == CNAuthorizationStatusNotDetermined) { CNContactStore * contactStore = [[CNContactStore alloc] init]; [contactStore requestAccessForEntityType:entityType completionHandler:^(BOOL granted, NSError * _Nullable error) { if(granted){ [self getAllContact]; } }]; } else if( [CNContactStore authorizationStatusForEntityType:entityType]== CNAuthorizationStatusAuthorized) { [self getAllContact]; } } } -(void)getAllContact { if([CNContactStore class]) { //iOS 9 or later NSError* contactError; CNContactStore* addressBook = [[CNContactStore alloc]init]; [addressBook containersMatchingPredicate:[CNContainer predicateForContainersWithIdentifiers: #[addressBook.defaultContainerIdentifier]] error:&contactError]; NSArray * keysToFetch =#[CNContactEmailAddressesKey, CNContactPhoneNumbersKey, CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPostalAddressesKey]; CNContactFetchRequest * request = [[CNContactFetchRequest alloc]initWithKeysToFetch:keysToFetch]; BOOL success = [addressBook enumerateContactsWithFetchRequest:request error:&contactError usingBlock:^(CNContact * __nonnull contact, BOOL * __nonnull stop){ [self parseContactWithContact:contact]; }]; } } - (void)parseContactWithContact :(CNContact* )contact { NSString * firstName = contact.givenName; NSString * lastName = contact.familyName; NSString * phone = [[contact.phoneNumbers valueForKey:#"value"] valueForKey:#"digits"]; NSStrubg * email = [contact.emailAddresses valueForKey:#"value"]; NSArray * addrArr = [self parseAddressWithContac:contact]; } - (NSMutableArray *)parseAddressWithContac: (CNContact *)contact { NSMutableArray * addrArr = [[NSMutableArray alloc]init]; CNPostalAddressFormatter * formatter = [[CNPostalAddressFormatter alloc]init]; NSArray * addresses = (NSArray*)[contact.postalAddresses valueForKey:#"value"]; if (addresses.count > 0) { for (CNPostalAddress* address in addresses) { [addrArr addObject:[formatter stringFromPostalAddress:address]]; } } return addrArr; } Just make sure that you ask the permission to read the contacts from device. Reference link: https://gist.github.com/willthink/024f1394474e70904728 Updated: For replacement for AddressBookUI you need to use CNContactPickerViewController. You can check the delegate methods which can be used to pickup the one or multiple contacts at a time. This will present a inbuilt UIViewController with all the contacts and you need to implement the delegate methods of it! To select one contact: contactPicker:didSelectContact: To select multiple (New Feature): contactPicker:didSelectContacts: CNContactPickerDelegate reference: https://developer.apple.com/library/ios/documentation/ContactsUI/Reference/CNContactPickerDelegate_Protocol/
Apple has introduced new framework for this for iOS9 and above please fine below link Link Edit: one more link :Link2
Private iOS Framework Returning NULL
I'm trying to use BatteryCenter and CommonUtilities private frameworks under iOS 9.1 with the help of nst's iOS Runtime Headers. It's for research purposes and won't make it to the AppStore. Here are their respective codes: - (void)batteryCenter { NSBundle *bundle = [NSBundle bundleWithPath:#"/System/Library/PrivateFrameworks/BatteryCenter.framework"]; BOOL success = [bundle load]; if(success) { Class BCBatteryDevice = NSClassFromString(#"BCBatteryDevice"); id si = [[BCBatteryDevice alloc] init]; NSLog(#"Charging: %#", [si valueForKey:#"charging"]); } } - (void)commonUtilities { NSBundle *bundle = [NSBundle bundleWithPath:#"/System/Library/PrivateFrameworks/CommonUtilities.framework"]; BOOL success = [bundle load]; if(success) { Class CommonUtilities = NSClassFromString(#"CUTWiFiManager"); id si = [CommonUtilities valueForKey:#"sharedInstance"]; NSLog(#"Is Wi-Fi Enabled: %#", [si valueForKey:#"isWiFiEnabled"]); NSLog(#"Wi-Fi Scaled RSSI: %#", [si valueForKey:#"wiFiScaledRSSI"]); NSLog(#"Wi-Fi Scaled RSSI: %#", [si valueForKey:#"lastWiFiPowerInfo"]); } } Although I get the classes back, all of their respected values are NULL which is weird since some must be true, e.g. I'm connected to Wi-Fi so isWiFiEnabled should be YES. What exactly is missing that my code doesn't return whats expected? Does it need entitlement(s)? If so what exactly?
In Swift, I managed to get this working without the BatteryCenter headers. I'm still looking for a way to access the list of attached batteries without using BCBatteryDeviceController, but this is what I have working so far: Swift 3: guard case let batteryCenterHandle = dlopen("/System/Library/PrivateFrameworks/BatteryCenter.framework/BatteryCenter", RTLD_LAZY), batteryCenterHandle != nil else { fatalError("BatteryCenter not found") } guard let batteryDeviceControllerClass = NSClassFromString("BCBatteryDeviceController") as? NSObjectProtocol else { fatalError("BCBatteryDeviceController not found") } let instance = batteryDeviceControllerClass.perform(Selector(("sharedInstance"))).takeUnretainedValue() if let devices = instance.value(forKey: "connectedDevices") as? [AnyObject] { // You will have more than one battery in connectedDevices if your device is using a Smart Case for battery in devices { print(battery) } } Swift 2.2: guard case let batteryCenterHandle = dlopen("/System/Library/PrivateFrameworks/BatteryCenter.framework/BatteryCenter", RTLD_LAZY) where batteryCenterHandle != nil else { fatalError("BatteryCenter not found") } guard let c = NSClassFromString("BCBatteryDeviceController") as? NSObjectProtocol else { fatalError("BCBatteryDeviceController not found") } let instance = c.performSelector("sharedInstance").takeUnretainedValue() if let devices = instance.valueForKey("connectedDevices") as? [AnyObject] { // You will have more than one battery in connectedDevices if your device is using a Smart Case for battery in devices { print(battery) } } This logs: <BCBatteryDevice: 0x15764a3d0; vendor = Apple; productIdentifier = 0; parts = (null); matchIdentifier = (null); baseIdentifier = InternalBattery-0; name = iPhone; percentCharge = 63; lowBattery = NO; connected = YES; charging = YES; internal = YES; powerSource = YES; poweredSoureState = AC Power; transportType = 1 >
You need to first access the BCBatteryDeviceController, after success block is executed, through which you can get list of all the connected devices. Here is the code for the same. Class CommonUtilities = NSClassFromString(#"BCBatteryDeviceController"); id si = [CommonUtilities valueForKey:#"sharedInstance"]; BCBatteryDeviceController* objBCBatteryDeviceController = si; NSLog(#"Connected devices: %#", objBCBatteryDeviceController.connectedDevices);
Is there any chance I can detect the Wifi band connected with my iPhone, like 802.11ac, in Objective-C?
Forget the grammar rules in my question since english is not my mother tongue; I want to detect my current Wifi hotspot, if it is in 2.4Ghz or 5Ghz in iOS environment,anyone got the idea or possibility? Here is my code below: NSString *wifiName = nil; CFArrayRef myArray = CNCopySupportedInterfaces(); if (myArray != nil) { CFDictionaryRef myDict = CNCopyCurrentNetworkInfo(CFArrayGetValueAtIndex(myArray, 0)); if (myDict != nil) { NSDictionary *dict = (NSDictionary*)CFBridgingRelease(myDict); wifiName = [dict valueForKey:#"SSID"]; } } return wifiName;
As I know you cant do this with native APIs. But there is a private API Stumbler for working with wifi in a more advanced way. [Warning]: If You Use Private APIs You Will Not Be Able To Distribute Your App through Appstore.