How to check if iPhone is in Airplane Mode with Swift - ios

I'd like to check whether flight mode is activated. If so, I need to show a warning message.
How can I check whether flight (airplane) mode is active using Swift?

The easiest way is to let iOS done it for you.
to go Info.plist -> add this **Application uses Wi-Fi (Boolean) YES*
To test: Kill your app -> turn on airplane mode -> open ur app: you should be able to see alert within the app. Tested on iPhone iOS9

As far as I know you can't -- or you can't using public API. My suggestion would be to call required devices and set corresponding notifications. If you really need to know if its flight mode, maybe you can do that with calling 3G, GPS, Wi-Fi etc. and check if every one is off.
I saw another suggestion with taking an in-app screenshot and checking for orange airplane ( does top contains orange part ).
Drawbacks are present for both, My suggestion is bad since your devices could be off for other, not related reasons.
Good luck.

If you are using Location Services, they should return with an error code of 1009 by presenting the following in log:
Geocode error: Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline."
If you check for a return code of -1009, you can recognize the user as offline and follow through accordingly.

You cant check the airplane mode is active or not , while you can check the cellular signal strength,
func getSignalStrength() -> Int {
let application = UIApplication.shared
let statusBarView = application.value(forKey: "statusBar") as! UIView
let foregroundView = statusBarView.value(forKey: "foregroundView") as! UIView
let foregroundViewSubviews = foregroundView.subviews
var dataNetworkItemView:UIView? = nil
for subview in foregroundViewSubviews {
if subview.isKind(of: NSClassFromString("UIStatusBarSignalStrengthItemView")!) {
dataNetworkItemView = subview
break
}
}
if dataNetworkItemView == nil
{
return 0
}
return dataNetworkItemView?.value(forKey: "signalStrengthBars") as! Int
}
Using this method you can get the signal strength and determine the device is in airplane mode or not .
In airplane mode it will return 0 while in network it will return strength.
Hope this will help you

Related

Why doesn't my iOS (Swift) app properly recognize some external display devices?

So I have an odd issue and my google-fu utterly fails to even provide me the basis of where to start investigating, so even useful keywords to search on may be of use.
I have an iOS application written in swift. I have a model hooked up to receive notifications about external displays. On some adaptors, I'm able to properly detect and respond to the presence of an external display and programatically switch it out to be something other than a mirror (see code block below). But with another adaptor, instead of just 'magically' becoming a second screen, I'm asked to 'trust' the external device, and it simply mirrors the device screen. Not the intended design at all.
func addSecondScreen(screen: UIScreen){
self.externalWindow = UIWindow.init(frame: screen.bounds)
self.externalWindow!.screen = screen
self.externalWindow!.rootViewController = self.externalVC
self.externalWindow!.isHidden = false;
}
#objc func handleScreenDidConnectNotification( _ notification: NSNotification){
let newScreen = notification.object as! UIScreen
if(self.externalWindow == nil){
addSecondScreen(screen: newScreen)
}
}
#objc func handleScreenDidDisconnectNotification( _ notification: NSNotification){
if let externalWindow = self.externalWindow{
externalWindow.isHidden = true
self.externalWindow = nil
}
}
The worst issue here is that because I'm connecting to an external display to do this, I can't even run this code through the debugger to find out what is going on. I don't know where to even begin.
Any ideas?
Edit:
Thanks to someone pointing out wifi debugging, I can tell you my notifications are firing off, but they're both firing at the same time, one after the other, when the external adaptor is disconnected.

Is there a way to tell if a MIDI-Device is connected via USB on iOS?

I'm using CoreMIDI to receive messages from a MIDI-Keyboard via Camera Connection Kit on iOS-Devices. My App is about pitch recognition. I want the following functionality to be automatic:
By default use the microphone (already implemented), if a MIDI-Keyboard is connected use that instead.
It's could find out how to tell if it is a USB-Keyboard using the default driver. Just ask for the device called "USB-MIDI":
private func getUSBDeviceReference() -> MIDIDeviceRef? {
for index in 0..<MIDIGetNumberOfDevices() {
let device = MIDIGetDevice(index)
var name : Unmanaged<CFString>?
MIDIObjectGetStringProperty(device, kMIDIPropertyName, &name)
if name!.takeRetainedValue() as String == "USB-MIDI" {
return device
}
}
return nil
}
But unfortunately there are USB-Keyboards that use a custom driver. How can I tell if I'm looking at one of these? Standard Bluetooth- and Network-Devices seem to be always online. Even if Wifi and Bluetooth are turned of on the device (strange?).
I ended up using the USBLocationID. It worked with any device I tested so far and none of the users complained.But I don't expect many users to use the MIDI-Features of my app.
/// Filters all `MIDIDeviceRef`'s for USB-Devices
private func getUSBDeviceReferences() -> [MIDIDeviceRef] {
var devices = [MIDIDeviceRef]()
for index in 0..<MIDIGetNumberOfDevices() {
let device = MIDIGetDevice(index)
var list: Unmanaged<CFPropertyList>?
MIDIObjectGetProperties(device, &list, true)
if let list = list {
let dict = list.takeRetainedValue() as! NSDictionary
if dict["USBLocationID"] != nil {
devices.append(device)
}
}
}
return devices
}

Can use DJI SDK to replicate "Pitch Lock" feature of DJI Go app?

I'm trying to replicate the "Pitch Lock" on / off feature of the DJI Go app. How can I do this?
I'm using XCode 8.2.1, building for iOS 10.1, connecting to an Osmo Mobile with an iPhone 6s attached. The Osmo Mobile has the latest firmware (version 01.30.01.52).
Everything works so far (registerApp, connecting via bluetooth, getting handheld button presses, getting gimbal battery updates, getting gimbal updates).
Setting setGimbalWorkMode to either .freeMode or .yawFollowMode doesn't seem to have any effect. No error is returned in the completion block, but there's no effect on Gimbal operation.
The gimbal behaves as if it is in .freeMode (always moves to the exact direction handheld stick is pointing), but DJIGimbalDelegate only receives .yawFollowMode updates (which is what the pitchLock mode should do).
Setting setGimbalWorkMode to other modes results in an error (as expected with Osmo Mobile device).
Here's how I'm trying to toggle pitchLock on/off.
#IBAction func pitchLockPressed(_ sender: UIButton) {
pitchLock = !pitchLock
if let gimbal = fetchGimbal() {
var workMode : DJIGimbalWorkMode = .freeMode // .freeMode .fpvMode and .unknown return error using Osmo Mobile
if pitchLock {
workMode = .yawFollowMode
}
gimbal.setGimbalWorkMode(workMode, withCompletion: { (error) in
if (error != nil) {
print("error workMode: \(error?.localizedDescription)")
self.pitchLock = !(self.pitchLock) // back to previous
}
})
}
}
Here's the delegate, which only reports .yawFollowMode no matter what I do:
func gimbal(_ gimbal: DJIGimbal, didUpdate gimbalState: DJIGimbalState) {
// var needUpdate = false
if lastReportedWorkMode != gimbalState.workMode {
lastReportedWorkMode = gimbalState.workMode
switch lastReportedWorkMode {
case DJIGimbalWorkMode.fpvMode:
print("FPV\n")
case DJIGimbalWorkMode.freeMode:
print("Free\n")
case DJIGimbalWorkMode.yawFollowMode:
print("Yaw-follow\n")
case DJIGimbalWorkMode.unknown:
print("Unknown\n")
}
}
Anyone getting setGimbalWorkMode to actually change gimbal modes?

Knowing programmatically if cell data is disabled for the app for iOS [duplicate]

I have an iOS app that makes some small network requests on app launch (resource updates, etc). If the user turns off cellular access for the app in iOS Settings, they get a prompt from iOS about network usage every time they launch. Is there a way to know programmatically that cellular data for this app has been disabled, so that I can disable the requests at startup?
So I found this on the apple dev forums from an Apple engineer (https://devforums.apple.com/message/1059332#1059332).
Another developer wrote in to DTS and thus I had a chance to
investigate this in depth. Alas, the news is much as I expected:
there is no supported way to detect that your app is in this state.
Nor is there a way to make a "no user interaction" network connection,
that is, request that the connection fail rather than present UI like
this. If these limitations are causing problems for your app, I
encourage you to file a bug describing your specific requirements.
https://developer.apple.com/bug-reporting/
So it looks like it is not possible to detect if cellular data for your app has been turned off.
Edit
I filed a radar for this requesting that it be added. I just got this notification in my radar
We believe this issue has been addressed in the latest iOS 9 beta.
I looked through the API diffs, but so far I can't find the new API.
As of iOS9, the capability to check the setting to enable/disable use of cellular data for your app (Settings/Cellular/AppName) is available using Apple's CTCellularData class. The following code will set cellularDataRestrictedState when it is run initially and then set it and log whenever it changes:
import CoreTelephony
var cellularDataRestrictedState = CTCellularDataRestrictedState.restrictedStateUnknown
let cellState = CTCellularData.init()
cellState.cellularDataRestrictionDidUpdateNotifier = { (dataRestrictedState) in
if cellularDataRestrictedState != .restrictedStateUnknown { // State has changed - log to console
print("cellularDataRestrictedState: " + "\(dataRestrictedState == .restrictedStateUnknown ? "unknown" : dataRestrictedState == .restricted ? "restricted" : "not restricted")")
}
cellularDataRestrictedState = dataRestrictedState
}
Unfortunately (as of iOS11) this seems to check only the state of the app's switch - if your app's switch is set to enabled and the user switches the Cellular Data master switch to disabled, this API will return the app's state as being "not restricted".
Just wanted to add an Objective C version of the above Swift code for future travellers.
- (void)monitorCanUseCellularData {
if (GCIsiOS9) {
CTCellularData *cellularData = [[CTCellularData alloc] init];
NSLog(#"%ld", cellularData.restrictedState);
// 0, kCTCellularDataRestrictedStateUnknown
[cellularData setCellularDataRestrictionDidUpdateNotifier:^(CTCellularDataRestrictedState state) {
NSLog(#"%ld", state);
self.canUseCellularData = cellularData.restrictedState ==2?true:false;
}];
}
}
I have found that the CTCellularData class needs some time to get to the correct value. In my implementation I call the didUpdateNotifier very early after appDidFinishLaunching. By the time my networking call are returning with errors I definitely have a correct value for the restricted state.
class CellularRestriction: NSObject {
private static var cellularData = CTCellularData()
private static var currentState = CTCellularDataRestrictedState.restrictedStateUnknown
static var isRestricted: Bool {
currentState = cellularData.restrictedState
return currentState == .restricted
}
static func prepare() {
if currentState == .restrictedStateUnknown {
cellularData.cellularDataRestrictionDidUpdateNotifier = { state in
currentState = cellularData.restrictedState // This value may be inconsistent, however the next read of isRestricted should be correct.
}
}
}
}
You can detect if cellular data disabled using NWPathMonitor class. (https://developer.apple.com/documentation/network/nwpathmonitor)
let cellMonitor = NWPathMonitor(requiredInterfaceType: .cellular)
cellMonitor.pathUpdateHandler = { path in
self.isCellConnected = path.status == .satisfied
}
Adding to dirkgroten's answer, you can use the Apple Reachability class, found here:
https://developer.apple.com/Library/ios/samplecode/Reachability/Introduction/Intro.html
It uses SCNetworkReachability, and is very straight forward to use, it will detect connectivity via Cell and WiFi as you will need to check both at start up.
There are lots of frameworks out there that will give you the status of your network connectivity, and of course you can roll your own. I've found AFNetworking to be one of the best. It has a singleton class called AFNetworkReachabilityManager that abstracts some of the complexities for you. Specifically you'll want to look at the two boolean properties:
reachableViaWWAN
reachableViaWiFi
There is also a reachability changed status block that you can set:
– setReachabilityStatusChangeBlock:
AFNetworking Github
AFNetworkReachabilityManager

How do I know if cellular access for my iOS app is disabled?

I have an iOS app that makes some small network requests on app launch (resource updates, etc). If the user turns off cellular access for the app in iOS Settings, they get a prompt from iOS about network usage every time they launch. Is there a way to know programmatically that cellular data for this app has been disabled, so that I can disable the requests at startup?
So I found this on the apple dev forums from an Apple engineer (https://devforums.apple.com/message/1059332#1059332).
Another developer wrote in to DTS and thus I had a chance to
investigate this in depth. Alas, the news is much as I expected:
there is no supported way to detect that your app is in this state.
Nor is there a way to make a "no user interaction" network connection,
that is, request that the connection fail rather than present UI like
this. If these limitations are causing problems for your app, I
encourage you to file a bug describing your specific requirements.
https://developer.apple.com/bug-reporting/
So it looks like it is not possible to detect if cellular data for your app has been turned off.
Edit
I filed a radar for this requesting that it be added. I just got this notification in my radar
We believe this issue has been addressed in the latest iOS 9 beta.
I looked through the API diffs, but so far I can't find the new API.
As of iOS9, the capability to check the setting to enable/disable use of cellular data for your app (Settings/Cellular/AppName) is available using Apple's CTCellularData class. The following code will set cellularDataRestrictedState when it is run initially and then set it and log whenever it changes:
import CoreTelephony
var cellularDataRestrictedState = CTCellularDataRestrictedState.restrictedStateUnknown
let cellState = CTCellularData.init()
cellState.cellularDataRestrictionDidUpdateNotifier = { (dataRestrictedState) in
if cellularDataRestrictedState != .restrictedStateUnknown { // State has changed - log to console
print("cellularDataRestrictedState: " + "\(dataRestrictedState == .restrictedStateUnknown ? "unknown" : dataRestrictedState == .restricted ? "restricted" : "not restricted")")
}
cellularDataRestrictedState = dataRestrictedState
}
Unfortunately (as of iOS11) this seems to check only the state of the app's switch - if your app's switch is set to enabled and the user switches the Cellular Data master switch to disabled, this API will return the app's state as being "not restricted".
Just wanted to add an Objective C version of the above Swift code for future travellers.
- (void)monitorCanUseCellularData {
if (GCIsiOS9) {
CTCellularData *cellularData = [[CTCellularData alloc] init];
NSLog(#"%ld", cellularData.restrictedState);
// 0, kCTCellularDataRestrictedStateUnknown
[cellularData setCellularDataRestrictionDidUpdateNotifier:^(CTCellularDataRestrictedState state) {
NSLog(#"%ld", state);
self.canUseCellularData = cellularData.restrictedState ==2?true:false;
}];
}
}
I have found that the CTCellularData class needs some time to get to the correct value. In my implementation I call the didUpdateNotifier very early after appDidFinishLaunching. By the time my networking call are returning with errors I definitely have a correct value for the restricted state.
class CellularRestriction: NSObject {
private static var cellularData = CTCellularData()
private static var currentState = CTCellularDataRestrictedState.restrictedStateUnknown
static var isRestricted: Bool {
currentState = cellularData.restrictedState
return currentState == .restricted
}
static func prepare() {
if currentState == .restrictedStateUnknown {
cellularData.cellularDataRestrictionDidUpdateNotifier = { state in
currentState = cellularData.restrictedState // This value may be inconsistent, however the next read of isRestricted should be correct.
}
}
}
}
You can detect if cellular data disabled using NWPathMonitor class. (https://developer.apple.com/documentation/network/nwpathmonitor)
let cellMonitor = NWPathMonitor(requiredInterfaceType: .cellular)
cellMonitor.pathUpdateHandler = { path in
self.isCellConnected = path.status == .satisfied
}
Adding to dirkgroten's answer, you can use the Apple Reachability class, found here:
https://developer.apple.com/Library/ios/samplecode/Reachability/Introduction/Intro.html
It uses SCNetworkReachability, and is very straight forward to use, it will detect connectivity via Cell and WiFi as you will need to check both at start up.
There are lots of frameworks out there that will give you the status of your network connectivity, and of course you can roll your own. I've found AFNetworking to be one of the best. It has a singleton class called AFNetworkReachabilityManager that abstracts some of the complexities for you. Specifically you'll want to look at the two boolean properties:
reachableViaWWAN
reachableViaWiFi
There is also a reachability changed status block that you can set:
– setReachabilityStatusChangeBlock:
AFNetworking Github
AFNetworkReachabilityManager

Resources