I want to check the internet connection in my iPhone without the use of Reachability Classes. i want to constantly check the connection when a particular event is triggered in my view. I also want to determine if the connection is from a Wifi or through 2G or 3G connection. I have already tried using Reachability classes. But these classes just return the value if the Wifi is On (Though the net cable is unplugged from the Wifi Router). I have tried
[Reachability reachabilityForInternetConnection]
and
[Reachability reachabilityWithHostName:#"www.google.com"];
But the above methods doesn't seem to work properly inspite of network disconnections.
Also is there any way we can determine the type of netwrok 2G or 3G in iOS6? I know that we have Core Telephony Framework that works only in iOS 7. But i just want to know if i can determine the cellular network iOS 6.0. Please help me.
Working code without reachability classes and also working in iOS 6:
- (NSNumber *) dataNetworkTypeFromStatusBar {
UIApplication *app = [UIApplication sharedApplication];
NSArray *subviews = [[[app valueForKey:#"statusBar"] valueForKey:#"foregroundView"] subviews];
NSNumber *dataNetworkItemView = nil;
for (id subview in subviews) {
if([subview isKindOfClass:[NSClassFromString(#"UIStatusBarDataNetworkItemView") class]]) {
dataNetworkItemView = subview;
break;
}
}
return [dataNetworkItemView valueForKey:#"dataNetworkType"];
}
And the value keys I've found so far:
0 = No wifi or cellular
1 = 2G and earlier?
2 = 3G?
3 = 4G
4 = LTE
5 = Wifi
Or in iOS7 use CoreTelephony framework
CTTelephonyNetworkInfo *telephonyInfo = [CTTelephonyNetworkInfo new];
NSLog(#"Current Radio Access Technology: %#", telephonyInfo.currentRadioAccessTechnology);
[NSNotificationCenter.defaultCenter addObserverForName:CTRadioAccessTechnologyDidChangeNotification
object:nil
queue:nil
usingBlock:^(NSNotification *note)
{
NSLog(#"New Radio Access Technology: %#", telephonyInfo.currentRadioAccessTechnology);
}];
Related
How to get Apps Using WLAN & Cellular Setting setting status in the picture below ?
How can I check that status(None, WLAN, WLAN&Cellular) for my App, so that I can show an alert to remind user of open this switch ~
When Reachability is NotReachable, there are 2 situation ,
The wifi is not connected
The Apps Using WLAN & Cellular Setting
is off
If we can get the SSID of current wifi, we can judge that the wifi is connected and the network switch is off ~
#import <SystemConfiguration/CaptiveNetwork.h>
BOOL networkSwitchOff = NO;
Reachability *reach = [Reachability reachabilityForInternetConnection];
NetworkStatus status = [reach currentReachabilityStatus];
if(status==NotReachable){ //Reachability NotReachable
NSArray *supportedInterfaces = (__bridge_transfer id)CNCopySupportedInterfaces();
id info = nil;
NSString *ssid = nil;
for (NSString *networkInfo in supportedInterfaces) {
info = (__bridge_transfer id)CNCopyCurrentNetworkInfo((__bridge CFStringRef)networkInfo);
if (info && [info count])
break;
}
if (info) {
NSDictionary *dctySSID = (NSDictionary *)info;
//we can't get ssid if wifi is not connected
ssid = [dctySSID objectForKey:#"SSID"];
}
networkSwitchOff = (ssid!=nil);
}
Okay, I'm working on a fun project that has a hurdle where I need to enable Bluetooth audio support for my iOS app.
The hurdle I'm at is that I simply can't even begin to get a list of connected Bluetooth audio devices. Even though my iPhone 5S recognizes my earpiece (a ~3 - 4 year old LG HBM-230, to be precise) and plays audio through it for phone calls, BOTH External Accessory and CoreBluetooth are giving me nothing useful when I query both.
I'm basing my own code off questions & answers I found for both the CoreBluetooth and External Accessory frameworks.
When my code simply tries to "scanForPeripheralsWithServices:nil" for any Bluetooth devices which Settings->Bluetooth say are visible and connected, the below code simply is NOT coming up with a single hit beyond the "CBCentralManagerStatePoweredOn" message in the console.
And this line in my code (with a valid EAAccessoryManager instance)
NSArray * connectedDevices = [self.eAAccessoryManager connectedAccessories];
also comes back with a nil array.
What could I be doing wrong?
B.T.W., I've made this code available as a GitHub project.
#implementation BluetoothManager
+ (BluetoothManager *)sharedInstance
{
static dispatch_once_t pred = 0;
__strong static id _bluetoothMGR = nil;
dispatch_once(&pred, ^{
_bluetoothMGR = [[BluetoothManager alloc] init];
});
return _bluetoothMGR;
}
- (id)init
{
self = [super init];
if(self)
{
dispatch_queue_t centralQueue = dispatch_queue_create("com.yo.mycentral", DISPATCH_QUEUE_SERIAL);
// whether we try this on a queue of "nil" (the main queue) or this separate thread, still not getting results
self.cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue options:nil];
}
return self;
}
// this would hit.... if I instantiated this in a storyboard of XIB file
- (void)awakeFromNib
{
if(!self.cbManager)
self.cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(#"hey I found %#",[advertisementData description]);
}
- (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals
{
NSLog( #"I retrieved CONNECTED peripherals");
}
-(void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals{
NSLog(#"This is it!");
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
NSString *messtoshow;
switch (central.state) {
case CBCentralManagerStateUnknown:
{
messtoshow=#"State unknown, update imminent.";
break;
}
case CBCentralManagerStateResetting:
{
messtoshow=#"The connection with the system service was momentarily lost, update imminent.";
break;
}
case CBCentralManagerStateUnsupported:
{
messtoshow=#"The platform doesn't support Bluetooth Low Energy";
break;
}
case CBCentralManagerStateUnauthorized:
{
messtoshow=#"The app is not authorized to use Bluetooth Low Energy";
break;
}
case CBCentralManagerStatePoweredOff:
{
messtoshow=#"Bluetooth is currently powered off.";
break;
}
case CBCentralManagerStatePoweredOn:
{
messtoshow=#"Bluetooth is currently powered on and available to use.";
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
[_cbManager scanForPeripheralsWithServices:nil options:options];
break;
}
}
NSLog(#"%#", messtoshow);
}
#end
First you will need to configure your applications audio session to allow bluetooth connections that support audio. You can do this in, for example, your application delegates - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method. Make sure you link the AVFoundation Framework and import in headers that will use it.
#import <AVFoundation/AVFoundation.h>// place in .h
[self prepareAudioSession];// called from application didFinishLaunchingWithOptions
- (BOOL)prepareAudioSession {
// deactivate session
BOOL success = [[AVAudioSession sharedInstance] setActive:NO error: nil];
if (!success) {
NSLog(#"deactivationError");
}
// set audio session category AVAudioSessionCategoryPlayAndRecord options AVAudioSessionCategoryOptionAllowBluetooth
success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
if (!success) {
NSLog(#"setCategoryError");
}
// activate audio session
success = [[AVAudioSession sharedInstance] setActive:YES error: nil];
if (!success) {
NSLog(#"activationError");
}
return success;
}
Every application has an audio session singleton that you can configure. The sessions category and mode (in this example I did not set the mode so it reverts to the default mode) declare your applications intentions as to how you would like audio routing to be handled. It follows an important rule of last in wins. This means that if the user plugs in a headset or in this case a bluetooth device that is a hands free peripheral (HFP) the system will automatically route the audio to the headset or bluetooth device. The users physical actions are used to determine audio routing. However if you wish to give the user a list of available routes Apple recommend using MPVolumeView class.
An example for adding MPVolumeView could be put in a UIViewController subclasses viewDidLoad method.
#import <MediaPlayer/MediaPlayer.h> // place in .h
// prefered way using MPVolumeView for user selecting audio routes
self.view.backgroundColor = [UIColor clearColor];
CGRect frameForMPVV = CGRectMake(50.0, 50.0, 100.0, 100.0);
MPVolumeView *routeView = [[MPVolumeView alloc] initWithFrame:frameForMPVV];
[routeView setShowsVolumeSlider:NO];
[routeView setShowsRouteButton:YES];
[self.view addSubview: routeView];
As of iOS 7 you can get all inputs like this
// portDesc.portType could be for example - BluetoothHFP, MicrophoneBuiltIn, MicrophoneWired
NSArray *availInputs = [[AVAudioSession sharedInstance] availableInputs];
int count = [availInputs count];
for (int k = 0; k < count; k++) {
AVAudioSessionPortDescription *portDesc = [availInputs objectAtIndex:k];
NSLog(#"input%i port type %#", k+1, portDesc.portType);
NSLog(#"input%i port name %#", k+1, portDesc.portName);
}
The portType you would be interested in is "BluetoothHFP". The portName property typically is the manufacturer/model which is what you would show to the user. (I've checked this with a non-LE bluetooth Motorola dinosaur and it works)
Because of the last in wins rule you will need to observe these two notifications (iOS 7 included). One to handle interruptions (such as phone calls or an alarm) and the second to be notified of route changes. Route change notifications is the one related to this question.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myInterruptionSelector:)
name:AVAudioSessionInterruptionNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myRouteChangeSelector:)
name:AVAudioSessionRouteChangeNotification
object:nil];
For iOS 6.x you could read the currentRoute property of AVAudioSession inside the myRouteChange: selector to get the new route, as this will get called when a headset or bluetooth device is connected.
- (void)myRouteChangeSelector:(NSNotification*)notification {
AVAudioSessionRouteDescription *currentRoute = [[AVAudioSession sharedInstance] currentRoute];
NSArray *inputsForRoute = currentRoute.inputs;
NSArray *outputsForRoute = currentRoute.outputs;
AVAudioSessionPortDescription *outPortDesc = [outputsForRoute objectAtIndex:0];
NSLog(#"current outport type %#", outPortDesc.portType);
AVAudioSessionPortDescription *inPortDesc = [inputsForRoute objectAtIndex:0];
NSLog(#"current inPort type %#", inPortDesc.portType);
}
Any iOS version < 6.0 you'll need the 'now deprecated' AudioSessionServices class. This class is a C api that instead of notifications it allows you to add property listeners.
I'll finish on this note - YOU DONT ALWAYS GET WHAT YOU WANT from the system. There are interruption handling notifications to observe and lots of error checking needed. I think this is a really good question and I hope this sheds some light on what it is you are trying to achieve.
Swift version
do {
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: .allowBluetooth)
try AVAudioSession.sharedInstance().setActive(true)
} catch {}
let availableInputs = AVAudioSession.sharedInstance().availableInputs
Hi i need to find out whether iPhone internet connected 3G or 2G or WIFI network
any suggestions
Thanks
Sravan
Download Reachability Class for iOS from this link:- https://github.com/tonymillion/Reachability
1)Add Reachability.h &.m in your Project, make sure you make it ARC compatible by adding flag -fno-objc-arc
2)Now, check the connection type in your view controller
Reachability *reachability = [Reachability reachabilityForInternetConnection];
[reachability startNotifier];
NetworkStatus status = [reachability currentReachabilityStatus];
if(status == NotReachable)
{
//No internet
}
else if (status == ReachableViaWiFi)
{
//WiFi
}
else if (status == ReachableViaWWAN)
{
//3G
}
You can use the Reachability library written by tonymillion.
If you don't wan to use ARC, there is also the Apple Reachability library.
Also take a look inside of < CoreTelephony/CTTelephonyNetworkInfo.h >
You will see that there is a currentRadioAccessTechnology property exposed on CTTelephonyNetworkInfo.
CTTelephonyNetworkInfo *netInfo = [[CTTelephonyNetworkInfo alloc] init];
NSLog(#"Radio access technology:\n%#",
netInfo.currentRadioAccessTechnology);
You can subscribe to changes via:
[NSNotificationCenter.defaultCenter
addObserverForName:CTRadioAccessTechnologyDidChangeNotification
object:nil
queue:nil
usingBlock:^(NSNotification __unused *notification) {
CTTelephonyNetworkInfo *current =
[[CTTelephonyNetworkInfo alloc] init];
NSLog(#"Updated Radio access technology:\n%#",
current.currentRadioAccessTechnology);
}];
Okay, I'm working on a fun project that has a hurdle where I need to enable Bluetooth audio support for my iOS app.
The hurdle I'm at is that I simply can't even begin to get a list of connected Bluetooth audio devices. Even though my iPhone 5S recognizes my earpiece (a ~3 - 4 year old LG HBM-230, to be precise) and plays audio through it for phone calls, BOTH External Accessory and CoreBluetooth are giving me nothing useful when I query both.
I'm basing my own code off questions & answers I found for both the CoreBluetooth and External Accessory frameworks.
When my code simply tries to "scanForPeripheralsWithServices:nil" for any Bluetooth devices which Settings->Bluetooth say are visible and connected, the below code simply is NOT coming up with a single hit beyond the "CBCentralManagerStatePoweredOn" message in the console.
And this line in my code (with a valid EAAccessoryManager instance)
NSArray * connectedDevices = [self.eAAccessoryManager connectedAccessories];
also comes back with a nil array.
What could I be doing wrong?
B.T.W., I've made this code available as a GitHub project.
#implementation BluetoothManager
+ (BluetoothManager *)sharedInstance
{
static dispatch_once_t pred = 0;
__strong static id _bluetoothMGR = nil;
dispatch_once(&pred, ^{
_bluetoothMGR = [[BluetoothManager alloc] init];
});
return _bluetoothMGR;
}
- (id)init
{
self = [super init];
if(self)
{
dispatch_queue_t centralQueue = dispatch_queue_create("com.yo.mycentral", DISPATCH_QUEUE_SERIAL);
// whether we try this on a queue of "nil" (the main queue) or this separate thread, still not getting results
self.cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue options:nil];
}
return self;
}
// this would hit.... if I instantiated this in a storyboard of XIB file
- (void)awakeFromNib
{
if(!self.cbManager)
self.cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(#"hey I found %#",[advertisementData description]);
}
- (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals
{
NSLog( #"I retrieved CONNECTED peripherals");
}
-(void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals{
NSLog(#"This is it!");
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
NSString *messtoshow;
switch (central.state) {
case CBCentralManagerStateUnknown:
{
messtoshow=#"State unknown, update imminent.";
break;
}
case CBCentralManagerStateResetting:
{
messtoshow=#"The connection with the system service was momentarily lost, update imminent.";
break;
}
case CBCentralManagerStateUnsupported:
{
messtoshow=#"The platform doesn't support Bluetooth Low Energy";
break;
}
case CBCentralManagerStateUnauthorized:
{
messtoshow=#"The app is not authorized to use Bluetooth Low Energy";
break;
}
case CBCentralManagerStatePoweredOff:
{
messtoshow=#"Bluetooth is currently powered off.";
break;
}
case CBCentralManagerStatePoweredOn:
{
messtoshow=#"Bluetooth is currently powered on and available to use.";
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
[_cbManager scanForPeripheralsWithServices:nil options:options];
break;
}
}
NSLog(#"%#", messtoshow);
}
#end
First you will need to configure your applications audio session to allow bluetooth connections that support audio. You can do this in, for example, your application delegates - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions method. Make sure you link the AVFoundation Framework and import in headers that will use it.
#import <AVFoundation/AVFoundation.h>// place in .h
[self prepareAudioSession];// called from application didFinishLaunchingWithOptions
- (BOOL)prepareAudioSession {
// deactivate session
BOOL success = [[AVAudioSession sharedInstance] setActive:NO error: nil];
if (!success) {
NSLog(#"deactivationError");
}
// set audio session category AVAudioSessionCategoryPlayAndRecord options AVAudioSessionCategoryOptionAllowBluetooth
success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
if (!success) {
NSLog(#"setCategoryError");
}
// activate audio session
success = [[AVAudioSession sharedInstance] setActive:YES error: nil];
if (!success) {
NSLog(#"activationError");
}
return success;
}
Every application has an audio session singleton that you can configure. The sessions category and mode (in this example I did not set the mode so it reverts to the default mode) declare your applications intentions as to how you would like audio routing to be handled. It follows an important rule of last in wins. This means that if the user plugs in a headset or in this case a bluetooth device that is a hands free peripheral (HFP) the system will automatically route the audio to the headset or bluetooth device. The users physical actions are used to determine audio routing. However if you wish to give the user a list of available routes Apple recommend using MPVolumeView class.
An example for adding MPVolumeView could be put in a UIViewController subclasses viewDidLoad method.
#import <MediaPlayer/MediaPlayer.h> // place in .h
// prefered way using MPVolumeView for user selecting audio routes
self.view.backgroundColor = [UIColor clearColor];
CGRect frameForMPVV = CGRectMake(50.0, 50.0, 100.0, 100.0);
MPVolumeView *routeView = [[MPVolumeView alloc] initWithFrame:frameForMPVV];
[routeView setShowsVolumeSlider:NO];
[routeView setShowsRouteButton:YES];
[self.view addSubview: routeView];
As of iOS 7 you can get all inputs like this
// portDesc.portType could be for example - BluetoothHFP, MicrophoneBuiltIn, MicrophoneWired
NSArray *availInputs = [[AVAudioSession sharedInstance] availableInputs];
int count = [availInputs count];
for (int k = 0; k < count; k++) {
AVAudioSessionPortDescription *portDesc = [availInputs objectAtIndex:k];
NSLog(#"input%i port type %#", k+1, portDesc.portType);
NSLog(#"input%i port name %#", k+1, portDesc.portName);
}
The portType you would be interested in is "BluetoothHFP". The portName property typically is the manufacturer/model which is what you would show to the user. (I've checked this with a non-LE bluetooth Motorola dinosaur and it works)
Because of the last in wins rule you will need to observe these two notifications (iOS 7 included). One to handle interruptions (such as phone calls or an alarm) and the second to be notified of route changes. Route change notifications is the one related to this question.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myInterruptionSelector:)
name:AVAudioSessionInterruptionNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(myRouteChangeSelector:)
name:AVAudioSessionRouteChangeNotification
object:nil];
For iOS 6.x you could read the currentRoute property of AVAudioSession inside the myRouteChange: selector to get the new route, as this will get called when a headset or bluetooth device is connected.
- (void)myRouteChangeSelector:(NSNotification*)notification {
AVAudioSessionRouteDescription *currentRoute = [[AVAudioSession sharedInstance] currentRoute];
NSArray *inputsForRoute = currentRoute.inputs;
NSArray *outputsForRoute = currentRoute.outputs;
AVAudioSessionPortDescription *outPortDesc = [outputsForRoute objectAtIndex:0];
NSLog(#"current outport type %#", outPortDesc.portType);
AVAudioSessionPortDescription *inPortDesc = [inputsForRoute objectAtIndex:0];
NSLog(#"current inPort type %#", inPortDesc.portType);
}
Any iOS version < 6.0 you'll need the 'now deprecated' AudioSessionServices class. This class is a C api that instead of notifications it allows you to add property listeners.
I'll finish on this note - YOU DONT ALWAYS GET WHAT YOU WANT from the system. There are interruption handling notifications to observe and lots of error checking needed. I think this is a really good question and I hope this sheds some light on what it is you are trying to achieve.
Swift version
do {
try AVAudioSession.sharedInstance().setCategory(.playAndRecord, options: .allowBluetooth)
try AVAudioSession.sharedInstance().setActive(true)
} catch {}
let availableInputs = AVAudioSession.sharedInstance().availableInputs
I'm trying to implement device discovery using bluetooth in IOS 5.0.1 iPhone 4S.
I'm using the private framework BluetoothManager.
My code is:
- (IBAction)searchForDevices:(id)sender
{
[self.indicator setHidden:NO];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(bluetoothAvailabilityChanged:) name:#"BluetoothAvailabilityChangedNotification" object:nil];
btCont = [BluetoothManager sharedInstance];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(deviceDiscovered:) name:#"BluetoothDeviceDiscoveredNotification" object:nil];
}
- (void)bluetoothAvailabilityChanged:(NSNotification *)notification
{
self.label.text = #"Availability changed!";
[btCont setDeviceScanningEnabled:YES];
}
- (void)deviceDiscovered:(BluetoothDevice *)device
{
[self.indicator setHidden:YES];
self.label.text = device.address;
My bluetooth headset is discovered.
deviceDiscovered callback function is called,
but device.address does NOT contain the MAC address of the bluetooth device. The app is crashing.
Also, device.name return the name of the notification (BluetoothDeviceDiscoveredNotification) instead of the name of the device discovered.
Any suggestions how can I retrieve the MAC address of my bluetooth headset this way?
use this code:
- (void)deviceDiscovered:(NSNotification *) notification {
BluetoothDevice *bt = [notification object];
NSLog(#"name: %# address: %#",bt.name, bt.address);
If this is a jailbreak app, you can use the key kLockdownBluetoothAddressKey via liblockdown.dylib