I use reachability to check internet connection when I connect to wifi it works fine. But when its connected to LTE network it gives me No Connection error, even though it is connected, I can browse the internet perfectly with LTE. I have also enabled App Transport Security in info.plist. I'm testing it on ios 10.1.1, do I have to do something to get internet access for my app in ios 10 using LTE?
Guru provided an excellent link in his comment. An updated way to check an LTE connection is indeed through CoreTelephony. Seeing as you asked in Swift though, I'll provide a Swift answer.
Make sure you have CoreTelephony.framework added under your project's Build Phases > Link Binary With Libraries
The code to check the connection in Swift would be as follows
import CoreTelephony // Make sure to import CoreTelephony
let constantValue = 8 // Don't change this
func checkConnection() {
let telephonyInfo = CTTelephonyNetworkInfo()
let currentConnection = telephonyInfo.currentRadioAccessTechnology
// Just a print statement to output the current connection information
print("\(constantValue)==D, Current Connection: \(currentConnection)")
if (currentConnection == CTRadioAccessTechnologyLTE) { // Connected to LTE
} else if(currentConnection == CTRadioAccessTechnologyEdge) { // Connected to EDGE
} else if(currentConnection == CTRadioAccessTechnologyWCDMA){ // Connected to 3G
}
}
Related
I need to get the device IP of the WiFi interface.
According to several StackOverflow threads, we could assume that "en0" corresponds to the Wi-Fi interface name :
https://stackoverflow.com/a/30754194/12866797
However, this feels like some kind of convention, not a standard.
Is there any consistent/standard way to retrieve the WiFi interface or the device WiFi IP address, using the iOS SDK ?
It would be nice if the API is available starting from iOS 11 but I won't be picky.
My best attempt was to use NWPathMonitor (iOS 12+) and monitor network changes corresponding to WiFi interfaces (NWInterface.InterfaceType.wifi) :
- (void) MonitorWifiInterface
{
m_pathMonitor = nw_path_monitor_create_with_type(nw_interface_type_wifi);
nw_path_monitor_set_update_handler(m_pathMonitor, ^(nw_path_t _Nonnull path) {
NSLog(#"[NetInterfaceUtilies] Network path changed");
nw_path_enumerate_interfaces(path, ^ bool (nw_interface_t _Nonnull itf)
{
NSLog(#"[NetInterfaceUtilies] Name : %s , Index : %u", nw_interface_get_name(itf), nw_interface_get_index(itf));
return true; // In order to continue the enumeration
});
});
nw_path_monitor_start(m_pathMonitor);
}
But I am not happy with it for the following reasons :
NWPathMonitor is supposed to be used for monitoring network changes : I haven't managed to get network information whenever I wanted, but only when WiFi has been set on/off.
I only managed to get the network interface name. But I can combine this data with the network interfaces retrieved with getifaddrs() in order to deduce the correct interface and IP : it's a step forward ?
It's "only" available starting from iOS 12.
I have an old app using GCDWebUploader of GCDWebServer to upload files into the app. And I copy the implementation code into a new project.
The problem: in this new project, the home page of GCDWebServer could be opened in iOS Simulator but cannot connect in real iPhone.
Environment:
Xcode 12.2, iOS 14
CocoaPods
It is weird since I got a worked app already. So I did some checks:
first, old app is worked. Means the home page could be opened.
all devices are under same wifi.
try to open http://192.168.1.5/ or http://192.168.1.5:80 in browser, safari said "Cannot open the page, because the server isn't responding", however I could ping 192.168.1.5 in terminal successfully.
restart my iPhone
compare info.plist between two projects
No result! Would you guys advice about what I missed, maybe some config in Xcode to allow HTTP communication or some capabilities to enable?
What in console:
[DEBUG] Did open IPv4 listening socket 3
[DEBUG] Did open IPv6 listening socket 4
[INFO] GCDWebUploader started on port 80 and reachable at http://192.168.1.5/
Visit http://192.168.1.5/ in your web browser
The code:
import GCDWebServer
import Foundation
class MyWebUploader {
// move webuploader to outside of init func to fix app crash issue.
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
lazy var webUploader = GCDWebUploader(uploadDirectory: self.documentsPath)
func initWebUploader() -> String {
var ipAddress = String()
webUploader.start()
webUploader.allowedFileExtensions = ["mp3", "aac", "m4a", "wav"]
if webUploader.serverURL != nil {
// retrieve IP address from URL
let str = webUploader.serverURL!.absoluteString
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -1)
let range = start..<end
let mySubstring = str[range]
ipAddress = String(mySubstring)
print("Visit \(webUploader.serverURL!) in your web browser")
} else {
ipAddress = "No Wifi connected"
}
return ipAddress
}
func stopWebUploader() {
webUploader.stop()
}
}
This issue is caused by the new permission in iOS 14 to find and connect to devices on your local network.
To fix it, we need to add following info in info.plist
<key>NSLocalNetworkUsageDescription</key>
<string>Reason for using Bonjour that the user can understand</string>
<key>NSBonjourServices</key>
<array>
<string>_http._tcp</string>
<string>_http._udp</string>
</array>
More details please see NSNetServiceBrowser did not search with error -72008 on iOS 14
I have two BluetoothHFP bluetooth devices connected to my iPad(bluetoothA2DP and bluetoothLE) and I need to detect which one is currently getting the audio. Below is the code I am using to detect what bluetooth is available :
let currentRoute = audioSession.currentRoute
for description in currentRoute.outputs {
if convertFromAVAudioSessionPort(description.portType) == convertFromAVAudioSessionPort(AVAudioSession.Port.bluetoothA2DP) {
//Do Something
break
}else if convertFromAVAudioSessionPort(description.portType) == convertFromAVAudioSessionPort(AVAudioSession.Port.bluetoothHFP) {
//Do Something
break
}else if convertFromAVAudioSessionPort(description.portType) == convertFromAVAudioSessionPort(AVAudioSession.Port.bluetoothLE){
//Do Something
break
}
}
What can I use to find out what one of the BluetoothHFP devices is currently getting audio?
You can distinguish between ports of the same type using description.portName and description.uid. Note that the name is not promised to be unique (it comes from the device). The UID is system-assigned and is not promised to be stable. It's only promised to be consistent with the owningPortUID property, and will be unique at any given time.
It happens to be true currently (iOS 13) that the UID is based on the hardware MAC address, and is stable. It's in the format aa:bb:cc:dd:ee:ff-tacl (the MAC address followed by -tacl). This has been true for a long time. I've been using this fact since at least iOS 8, and it's very likely it's been true as long as AVAudioSession has been around. But it's not promised, and is exactly the kind of thing that Apple has been known to change without notice.
"Low Data Mode" is introduced in iOS 13. See "Settings" section Apple's iOS 13 overview:
I couldn't find any developer documentation on this.
Is this something third party app developers can opt into, as suggested by MacRumors? Or is will it just suspend background activity when not connected to Wi-Fi, as suggested by AppleInsider?
To determine if iOS is currently in Low Data mode, you can use the Network library:
import Network // Put this on top of your class
let monitor = NWPathMonitor()
monitor.pathUpdateHandler = { path in
if path.isConstrained {
// Path uses an interface in Low Data Mode.
}
else if path.isExpensive {
// Path uses an interface that is considered expensive, such as Cellular or a Personal Hotspot.
}
}
monitor.start(queue: DispatchQueue.global(qos: .background))
URLSession supports LowData mode in iOS 13.
Steps
Provide two different resources for high resolution and low resolution(low data mode)
If statusCode == 200 (low data mode is disabled in setting).
If error.networkAvailableReason == .constrained (low data mode is enable in settings)
Check out Advances in Networking, Part 1 from WWDC 2019 from 16:00 for a demo and sample code. You can use Combine to make the code simpler, but this is not required.
First of all, you need to configure your URLSession (NSURLSession) to either allow or disallow expensive or constrained network connections to be opened.
You can do that by changing URLSession's respective properties allowsExpensiveNetworkAccess or allowsConstrainedNetworkAccess to false (NO).
If a URLSessionTask results in an error that is either an NSURLErrorNotConnectedToInternet error containing NSURLErrorNetworkUnavailableReasonKey entry in userInfo (Objective-C) or an URLError with a non-nil NetworkUnavailableReason property set (Swift), then you need to act accordingly.
Those reasons can be:
expensive
constrained
cellular
The cellular reason has sort of been there since iOS 7, so it's not new, but the entire reason enumeration is, as Apple streamlined connection type handling a bit this year.
Here is the solution in Xamarin, for those interested:
NWPathMonitor monitor = new NWPathMonitor();
monitor.SetUpdatedSnapshotHandler(path =>
{
if (path.Status == NWPathStatus.Satisfied)
{
if(path.IsConstrained)
{
// Path uses an interface in Low Data Mode.
}
}
});
monitor.SetQueue(CoreFoundation.DispatchQueue.DefaultGlobalQueue);
monitor.Start();
I'm experimenting with "Reachability" in Xmarin, using the Reachability class (sample here), but I cannot get the "IsHostReachable" feature to work.
I do realize that the Reachability class utilizes the NetworkReachability class but no matter which class I use the TryGetFlags() method always passes back the NetworkReachabilityFlags argument with a zero (0) value.
I started out using the Reachability class' method but while debugging I saw that the problem seems to originate in NetworkReachability. I tried the following code just to make sure:
using (var r = new NetworkReachability(host))
{
NetworkReachabilityFlags flags;
if (r.TryGetFlags(out flags)) // <-- flags is always 0 (zero)
return (flags & NetworkReachabilityFlags.Reachable) == NetworkReachabilityFlags.Reachable;
return false;
}
Like I said the flags variable is passed back with a zero (0) value, regardless of the device's current connection status. The host I'm testing against is a intranet web app that is only available when I'm on my company's WIFI. I have tested debuging the iPhone while connected and double checked by simply trying to browse to the host in Safari, which works.
The API is poorly documented but I'm suspecting I might need to initialize the NetworkReachability class somehow.
Any ideas?