Is it possible to get wifi signal strength in ios 9 - ios

I want to check WIFI signal strength to display some kind of message for weak WIFI signal.
I fount that it is not possible in iOS 8 and older.
Is it possible to get wifi signal strength in iOS 9? and if answer is yes then How?

Yes , it is possible in iOS 9.Look into NEHotspotNetwork

Register your app as Hotspot helper. (forums.developer.apple.com/message/30657#30657)
#import <NetworkExtension/NetworkExtension.h>
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;
}

It is, but you need permission from Apple. Once Apple allows you to use the HotspotHelper framework, you'll be able to create profiles with the hotspot helper entitlements. Check this post: How to get Wifi SSID in iOS9 after CaptiveNetwork is deprecated and calls for Wifi name are already blocked

Related

Flutter : IOS to IOS Broadcast Beacon not working

I'm currently building an app that turns my device into a Beacon while simultaneously scanning for other Beacons.
So I can keep track of beacons that I had come in contact with.
Problem
Current I've tested this code in the following Scenarios:
Android TO Android - Broadcasting & Scanning - Working well
Android To IOS - BroadCasting & Scanning Both ways - Working well
IOS to IOS - Not Working (When I broadcast UUID from IOS Device, I can see UUID in Android device but I can't see UUID in any IOS device.)
I installed this piece of code in 4 devices (2 Android & 2 IOS). Now all 4 devices are broadcasting different UUID's and at the same time listening.
In Android Devices, I see 1 UUID of another Android Device and 2 UUID's of IOS Devices
In IOS Devices, I see 2 Android UUID's but I cannot see another IOS Device UUID.
This is very strange, and I need help to solve this, please!
I've currently implemented 2 packages to achieve this functionality :
(1) For broadcast
beacon_broadcast: https://pub.dev/packages/beacon_broadcast
version : 0.2.1
(2) For scan other beacons
flutter_blue: https://pub.dev/packages/flutter_blue
version : 0.6.3+1
These are some glimpse of my code
(1) For Broadcasting
String UUID = 'DYNAMIC_UUID_FOR_EACH_DEVICE';
static const MAJOR_ID = 1;
static const MINOR_ID = 30;
static const TRANSMISSION_POWER = -59;
static const IDENTIFIER = 'com.example.myDeviceRegion';
static const LAYOUT = 'm:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24';
static const MANUFACTURER_ID = 0x004c;
BeaconBroadcast beaconBroadcast = BeaconBroadcast();
beaconBroadcast
.setUUID(UUID)
.setMajorId(MAJOR_ID)
.setMinorId(MINOR_ID)
.setTransmissionPower(TRANSMISSION_POWER)
.setIdentifier(IDENTIFIER)
.setLayout(LAYOUT)
.setManufacturerId(MANUFACTURER_ID);
.start();
(2) For Scanning
FlutterBlue flutterBlue = FlutterBlue.instance;
flutterBlue.startScan(timeout: Duration(seconds: 30));
flutterBlue.scanResults.listen((List<ScanResult> results) {
print('scanningListen...');
for (ScanResult result in results) {
result.advertisementData.manufacturerData.forEach((item, hexcodeAsArray) => {
print("calculated UUID String : " + calculateHexFromArray(v));
_addToScanResult(calculateHexFromArray(v));
});
}
}
String calculateHexFromArray(decimalArray) {
String uuid = '';
decimalArray.forEach((i) => {uuid += i.toRadixString(16).padLeft(2, '0')});
String uuid1 = uuid.substring(4, uuid.length - 12);
return uuid1.toUpperCase();
}
Unfortunately, you cannot use FlutterBlue to detect iBeacon packets on iOS.
Why? FlutterBlue uses raw bluetooth scanning to detect beacons, which under the hood means using the native CoreBluetooth scanning APIs on iOS. Apple blocks CoreBluetooth APIs from reading the raw bytes of any bluetooth advertisement decodable as an iBeacon advertisement. While this may sound crazy, it is likely motivated by misguided security concerns by Apple. Read more in my blog post here: CoreBluetooth Doesn't Let You See iBeacons
Two options to fix this:
Switch to using the AltBeacon format. Simply change LAYOUT = 'm:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25'; and MANUFACTURER_ID = 0x0118;
This will work, but has the disadvantage of the advertisement only being detectable on iOS in the foreground.
Switch to using a different detection library on iOS that uses CoreLocation (the only API allowed to detect iBeacon on iOS) instead of CoreBluetooth. That means giving up FlutterBlue in favor of FlutterBeacon or similar.

Push notification not register to the app on iOS 13

I build my app and I put a breakpoint in didRegisterForRemoteNotificationsWithDeviceToken but it's not triggered.
It works fine on other versions of iOS.
Is this a bug in iOS 13 or did I miss something new in iOS 13?
I use Xcode Beta 6 and iOS 13 beta 8.
The aforesaid problem could also be resolved by reconnecting wifi or switching between wifi and cellular data.
Moreover, following changes in iOS 13 affected push notification implementation.
Prior to iOS 13 many of us used to do
(deviceToken as NSData).description
// Used to return as follows
"<965b251c 6cb1926d e3cb366f dfb16ddd e6b9086a 8a3cac9e 5f857679 376eab7C>"
let tokenData = deviceToken as NSData
let token = tokenData.description
let token = "\(deviceToken)".replacingOccurrences(of: " ", with: "")
.replacingOccurrences(of: "<", with: "")
.replacingOccurrences(of: ">", with: "")
In iOS 13 apple has changed the implementation of its description method for NSData class.
So, it returns
"{length = 32, bytes = 0x965b251c 6cb1926d e3cb366f dfb16ddd ... 5f857679 376eab7c }" // in iOS 13.
Which ended up breaking push notifications implementation for many applications.
From now on, if you need to convert your push notification registration deviceToken into a Base16-encoded / hexadecimal string representation, you should do the following for Swift language
let deviceTokenString = deviceToken.map { String(format: "%02x", $0)
}.joined()
For Objective C, use following code
- (NSString *)hexadecimalStringFromData:(NSData *)deviceToken {
NSUInteger dataLength = deviceToken.length;
if (dataLength == 0) {
return nil;
}
const unsigned char *dataBuffer = (const unsigned char *)deviceToken.bytes;
NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for (NSInteger index = 0; index < dataLength; ++index) {
[hexString appendFormat:#"%02x", dataBuffer[index]];
}
return [hexString copy];
}
I came across a comprehensive article on the given topic
https://nshipster.com/apns-device-tokens/
As what I understood from trying a lot things about this issue is : sometimes iOS forcing the kind of connection to register device token to apple server.
If you are on WI-FI and didRegisterForRemoteNotificationsWithDeviceToken not called even though you are sure your implemantation of remote notification flow, try switching 3G or 4G. If it is not possible (a test device with no sim) try going to flight mode and activate wireless (which solved our problem).
If you are on 3G - 4G, try switching to wireless connection (There may be a problem if you are using vpn, proxy etc. disable all of them first).
If not other Stackoverflow users suggested deleting the app then restarting the device.
If the didRegisterForRemoteNotificationsWithDeviceToken is not triggering at all, try this.
I tried a lot to fix this issue with my wifi network, but it didnt fixed. So I changed my network to the cellular data and the didRegisterForRemoteNotificationsWithDeviceToken started triggering again
Also, if you used your internet connection in the MAC to share using USB. Turn it off & connect your IPhone with a normal wifi or mobile data.
if u use the testing device (without sim), try to put the sim card and install the app and gave the , it's worked for me.

Will en0 always be Wi-Fi on an iOS device?

I’m trying to get the IP address of the wifi interface on iOS devices using getifaddrs() and searching for the en0 name. This is working fine, but it assumes that en0 is always Wi-Fi. Is there some way to ensure that the interface I’m querying is specifically Wi-Fi for future proofing?
I use the following to find the wifi information by looking for a device which has a BSSID for the wifi station. It will also have a SSID.
The following class method returns the wifi info dictionary only. It is a simple extension to also return the device label (ifname variable). It is usually en0, as you have noted, but this would work as a way to make sure you pick up the wifi if it was not en0 in the future.
+ (NSDictionary *)getWifiInfo {
NSDictionary *ret=nil;
// Get the supported interfaces.
NSArray *ifs = (__bridge_transfer id)CNCopySupportedInterfaces();
// Find one with a BSSID and return that. This should be the wifi.
for (NSString *ifnam in ifs) {
NSDictionary *info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)ifnam);
NSLog(#"Network device found = %#", info.description);
if (info[(__bridge NSString *)kCNNetworkInfoKeyBSSID]) {
// Return this as it should be the right one given it has a MAC address for the station
ret=info;
}
}
NSLog(#"Exit: returning wifi info = %#", ret.description);
return ret;
}
Once you have the device label based on BSSID, you can then use getifaddrs to get its IP, gateway etc knowing it is the wifi device.
NB This returns nil in the iOS simulator as there is no wifi detected, so for testing you need some workaround code to meet your needs.
A hacky option is to find the IP address with an associated MAC of 02:00:00:00:00:00. iOS hides the MAC address from coders and it has this value.

iOS MDM: Can we get to know whether device is rooted or jailbroken?

I am working on MDM implementation for iOS. I want to know whether there any command using which we can get to know whether iOS device is rooted or jailbroken?
I had seen the MDM protocol reference and I haven't found any field in DeviceInformation command to know this.
How server can know this status from device?
The Apple MDM protocol does not have a way to check if a device is jailbroken. MDM vendors will usually come up with their own solution for this.
You can look for Cydia (or similar apps) with NSFileManager. And you should check if you have access to the bash on the phone. You can try something like this:
- (BOOL) isJailbroken
{
//If the app is running on the simulator
#if TARGET_IPHONE_SIMULATOR
return NO;
//If its running on an actual device
#else
BOOL isJailbroken = NO;
//This line checks for the existence of Cydia
BOOL cydiaInstalled = [[NSFileManager defaultManager] fileExistsAtPath:#"/Applications/Cydia.app"];
FILE *f = fopen("/bin/bash", "r");
if (!(errno == ENOENT) || cydiaInstalled) {
//Device is jailbroken
isJailbroken = YES;
}
fclose(f);
return isJailbroken;
#endif
}
This code is not really tested.. let me know if it worked.

CoreWLAN or any other public API for IOS 7

I'm looking for a way to scan available Wi-Fi access points (hotspots) from my IOS-app.
All that I need is a list of active at the moment hotspot names, where a device is able to connect to.
Like Safari shows a list of Wi-Fi hotspots when we start or activate it.
I'd like to publish the app on App Store, so I can't use any kind of Private API's (right?).
And unfortunatelly CoreWLAN.framework is unavailable for IOS (right?).
So, is it possible to achieve my target? Can I collect available access points names (SSID) some way?
There is no Public APIs at the moment that you can use to get a list of available Wi-Fi access points. As you're planning to publish on the App Store, Private APIs are not an option.
The closest thing you can achieve is getting your currently connected Wi-Fi name and details which can be achievied with CaptiveNetwork with the SystemConfiguration.framework.
+ (NSString *)currentSSID
{
NSString *ssid;
NSArray *interfaces = (__bridge_transfer id)CNCopySupportedInterfaces();
for (NSString *interfaceName in interfaces) {
NSDictionary *informations = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)interfaceName);
if (informations[#"SSID"]) {
ssid = informations[#"SSID"];
}
}
return ssid;
}

Resources