What is the best way to COMPLETELY restart the iOS Bluetooth BTLE central and peripheral managers, after communication stops between two iOS devices (iPad-mini)?
Sometimes after a few minutes, my BTLE communication stops (central can not get response from peripheral, though debug output of each device shows app still running and central app still is trying to scan peripheral, and peripheral is still advertising), and will not start again:
after stopping scanning and stopping advertising, comm still doesn't work;
after re-opening the app, comm still doesn't work(!);
after POWER CYCLING the iPads comm works again, but then after a few minutes dies.
Therefore, something I'm doing is clobbering maybe the iOS core Bluetooth software.
Sometimes there are error messages from the underlying BTLE layer.
BACKGROUND:
Each iPad in this system alternately works as central, to read/write data to others, and then as peripheral, to be read by others. Never at the same time, and with a 1 second delay between transistions.
The bluetooth stack is not the most robust part of iOS. This may have improved in iOS7 but issues have always existed. You most probably are stressing the system so that this hang happens more often. You should create a bug report and send it to Apple. Or create a TSI, as a developer you have two of those every year. They are the only ones who can do something about it.
To solve the issue, restarting the app usually helps but sometimes bluetooth needs to be turned on/off or worst case the device needs to be power cycled. Unfortunately, there is not programmatic way to do any of these.
Related
I am trying to reverse engineer the API of an IoT device using mitmproxy. My setup is an iphone, computer running on MacOS 10.14, and an IoT device (watering pump) that can only access the wireless network after being plugged into the computer via USB connection, i.e. a not genuinely WiFi device. My phone is configured to point to the computer, which is running mitmproxy on a standard configuration.
When I send instructions from the app controlling the device on my phone to the device itself, presumably these instructions are sent to the computer, to the device cloud server, and then to the device. With these assumptions, one would think that they would see the flow of POST requests in mitmproxy before observing the results of those instructions. That is, if you send an instruction to turn on the pump, you'd think you'd see POST request containing that instruction show up in the mitmproxy flows before you see the pump turn on.
However that is not the case here. What happens is that, when I send instructions from the app, I observe the expected behavior from the IoT device, and then the flow of requests appear on the mitmproxy console seemingly at random. There seems to be no determinate relationship between the instructions I send and the requests that appear; they show up 5 seconds later, 5 minutes later, or 30 minutes later. Is this an intentional security feature? To somehow jam MITMproxies so that hackers cannot easily isolate the knowledge of which packet is performing which instruction? Or is it just something that I am doing wrong? Does anyone have any ideas as to what could be happening hear and potential solutions for making the flow of requests appear in real time? Ty
I am new to iPhone/iPad development and I am close to finishing up my first app and I am looking for some general advice.
I know it is important to test on actual devices and not just the simulator. What are the types of things people generally encounter when testing on a deal device that they don't see in the simulator?
The app itself is mainly a way to track online deals and that type of thing. It doesn't need anything special in term of using things like the camera or GPS.
It's just general usage testing. The device performs in an entirely different environment than your computer, and it's the best way to make sure if you push your app out to devices, that nothing unexpected will happen. For example, the phone/pad may have limited data coverage, low memory situations, incoming calls etc.. These situations are a lot more common on devices, then when people emulate it though the simulator.
On a hardware point of view, the device uses a different processor architecture than your Mac, which also needs to be accounted for (not as much as other cases, but you need to cover your bases). The Mac also cannot reliably emulate RAM, Disc Space, Processor Speed etc...hence testing on the device is useful here also.
Obviously there are some features you can only test on devices, such as Camera, GPS (and not so obviously iPod library usage), and if your app uses them it'd be careless not to test on a device.
Overall if you're intending to release your application to the App Store, or to devices at least, it's worth testing on the device itself. Only then can you be sure that it will act and perform as expected on the platform you intend to target. The simulator is only a simulator after all, not the real thing!
First of all: the user experience is very different.
The mouse based interaction is very different from a touch interaction. focusing at a monitor feels very different then looking on a device on the palm of your hand.
Also the experience of animations running on the simulator and the real device can be very different.
And the usage in the simulator won't tell you anything about the battery consumptions to be witnessed on the real device.
My opinion: every app that will be shipped to the App Store or customer for testing should be tested several different real devices. No excuses.
Simulator runs a lot slower than the real device.
Real device could run out of memory when Simulator doesn't or vice versa.
In app purchases, if you have included them
Orientations (not that
they are unavailable on simulator, but it is easy to forget it
there!)
App life cycle testing - bringing your app to foreground and
background.
Network access - can matter when you access the network from device through wireless or cellular network vs LAN/wifi on your mac. There is a huge testing to be done under the umbrella called Reachability if your app uses any of the resources across the net. You are bound to provide an alert if network is unreachable before using any such resources, as per app store requirements.
We are in the process of developing an method of caching so that our app can continue to operate in an area with very little/no signal.
Obviously users will try to continue to use functions that require data and we need to handle the inevitable failure of these requests appropriately.
Essentially we are sat in the office, switching airplane mode on and off to simulate entering/exiting signal then adjusting our app to fix any issues this may arise.
What I'd like to know is, is using airplane mode going to give us a reasonable simulation of entering/exiting an area with no data or are there other implications?
I've seen questions raising the issue that the 3G/EDGE connection may not always wake up after airplane mode is switched on - while I appreciate this method is no way as good as actually being out in the field testing, if we can get a reasonable simulation and account for the majority of the problems that arise then I think this is an acceptable tradeoff.
I apologise if this has been asked before, I did do a search on here & on google but couldn't find any appropriate results.
You should try the Network Link Conditioner
There is a WWDC 2012 session called Networking Best Practices that mentions it (but he does not explain how to use it there).
To get it, you have to go to XCode/Open Developer Tool/More Developer Tools.. and download the latest Hardware IO Tools for XCode.
Once you install it from the IO Tools pkg, "Network Link Conditioner" will appear in System Preferences
You can then do something like 100% packet loss to simulate one of those routers that pretends you are connected but actually doesn't work.
On iOS, the network link conditioner is under Settings / Developer (you must have enabled Developer mode in XCode first to see it)
The main problem is that in the Airplane Mode the networking operations fail fast, while spotty mobile signal will lead to timeouts and a-few-bytes-an-hour speeds. This is usually a significant difference from the UI viewpoint. (It might be worth a try to use some bandwidth throttle to starve the testing machine and see how it behaves when the network starts to break?)
A few years back, when testing remote devices which used the cell network to communicate with the 'home base', we did things like move them into a shielded room (make shift), place large shields on three of four sides to force them to connect to a certain tower (and therefore, network), etc. Brute force physical methods. Since this actually cuts off the signal, it may be a more realistic approach.
You may also want to try this through your wlan-router. First, disable data roaming on your iPhone. Then, let the iPhone be connected to the internet through your wlan network. Then, disconnect the gateway on your wlan router while your iPhone is still connected to the wlan network.
This depends on what failure modes you are trying to test.
I use Airplane mode as a first pass check to make sure an app submission isn't quickly rejected.
Other network failure handling checks might include:
3G only (no wifi).
WIFI only (in Airplane mode).
Pulling the power cord on the WIFI access point.
Pulling the network cable from the back of the WIFI access point after connecting to it (Reachability may falsely say yes).
Walking in and out of a basement
elevator (or other Faraday cage) in the middle of a transfer.
Driving between 2 cell towers during a data transfer.
Walking between 2 enabled WIFI access points between connection and data transfer.
Starting the app after more than 30 minutes of device inactivity (radios may be idle).
Running the app while another app (Safari, Mail) is downloading in the background.
etc.
Building a desktop version of my mobile app and providing the user syncing over wifi. Everything works great in the simulator - no problems resolving net services (which are published by the desktop app) or noticing when services become unavailable.
The problem is when I run the app on the phone services are discovered and resolved (sometiems) but the NSNetServiceBrowser never notices when a service becomes unavailable. When this happens the net service browser constantly finds a net service (that is no longer published) resolves it but then can't connect to it. After several failed attempts the service browser delegate's "didRemoveService" is finally called and the app begins to behave correctly again.
I'd post my code but I've discovered the same issue is happening in Apple's WiTap example. Services are published and discovered but once they are made unavailable the client running the service browser doesn't update - and repeatedly tries to resolve a service that "shouldn't" exist.
I've discovered that running WiTap with wifi turned off (so Bonjour uses bluetooth) everything works fine. I can't find anyone complaining about WiTap not working and can't find this issue anywhere else online. Any reason - possibly with iPhone OS or my wireless network - why a net service browser can find and correctly resolve (but can't connect to) services that are unavailable?
Bonjour/NSNetServiceBrowser on the iPhone/iPod Touch will utilize both Wifi and Bluetooth for service discovery--at least on supported devices. Each time you begin browsing for services, it will search both WiFi and Bluetooth (which you can verify in the iPhone's Console, in Organizer). Since your Simulator "device" cannot use Bluetooth, your iPhone discovers it over WiFi. However, if you are using NSNetService to publish on your iPhone, then you are publishing over both WiFi and Bluetooth as well (if supported and enabled). NSNetServiceBrowser, when running on BT-capable hardware, will dutifully find that both instances, and report both via delegate callbacks.
Bluetooth PAN setup takes longer than publishing via Wifi, so the BT-discovered services often show up well after all the Wifi-based services have been discovered and resolved. When testing two real devices, I've even seen both services show up in my UI (usually only after the other phone crashes).
It does make for some frustrating coding, though. Your best bet is to utilize netService:didNotResolve: to either (i) retry resolution, or (ii) invalidate the netService instance and wait for the other phone to relaunch their app.
Also, there are a couple of other areas things can go wrong. Since the NSNetService instance provided to you is autoreleased, you need to retain it. Most people add it to an NSMutableArray or NSMutableDictionary. If that's the case, make sure that you have properly initialized it before adding the object. Since messages to nil are perfectly ok, if you send addObject: to nil it will appear as though everything is working fine. Except that it isn't. This crops up very often in Bonjour troubleshooting, and happens to the best of us. Make sure that your NSNetService gets scheduled into an actively running runloop, and one that is running in default or common modes.
There is an open bug filed with Apple (as of 10/4/09) whereby every so often, a Bonjour update will not result in a delegate method getting fired. I have only observed this occurring on a 3GS. The result is a client app that is out of sync with the network.
NSNetServiceBrowser should consistently notify when a service leaves the network (under nominal conditions). The bug above is only an intermittent one, and apparently, hardware specific. If you see it occurring consistently, then it's likely that your app is throwing an exception. If you are using background threads, this can occur without causing your whole app to crash. You may want to check your iPhones Console and logs for error messages. Make sure you have set a breakpoint on the symbol objc_exception_throw.
Here's another troubleshooting tip that I've found invaluable. Monitor Bonjour broadcasts on your dev machine via Terminal using the following command: dns-sd -B _serviceName. This will let you see all comings and goings on your local network for your service. If your app quits, but dns-sd does not show a Remove event, then your code needs revisiting. If dns-sd shows a remove event, but your other apps don't process it correctly, you may be seeing the above mentioned bug. It may also be the case that your code isn't doing what you think it's doing. And remember, this will only help you troubleshoot Wifi-to-Wifi service Bonjour. Bluetooth to Bluetooth is not supported from the iPhone Simulator.
Read the full article, Troubleshooting Bonjour Networking for the iPhone, at my dev blog.
I have two physical iPod touch devices. If I try running a program that uses a GKPeerPickerController to find another iPod touch running the same program, they just stay at the peer picker screen without any progress. Both have bluetooth enabled. I have tried my own program, along with Apple's GKTank sample app. Neither of the iPods seem to be able to detect bluetooth devices, such as computers in discoverable mode... could this have anything to do with it?
I was able to fix this problem by restoring the software on the older iPod. I wonder if jailbreak may have caused this issue?
A couple assumptions are throwing you off:
The GameKit Bluetooth stuff runs its own protocol, which doesn't involve traditional Bluetooth pairing or discoverability.
The simulator doesn't support connecting to devices via GameKit, so you need to test this with two real devices (or two computers, as the simulator will run the GK protocol over your current TCP connection [ethernet, wifi, etc]).
The Bluetooth bring-up of TCP/IP and Bonjour is really slow, so your first connection will often take upwards of 30 seconds to do any discovery. Even then, it seems flaky to me.
Jailbreaking your iPhone puts everything in play. You should expect stuff to not work, and be grateful if/when it does.
Gamekit only work on second generation iPod Touches (and iPhone 3G and 3GS). You didn't say whether what version your touches are.
I have been getting this error throughout the development of my game. It also leads to other problems when trying to reconnect to another game as the peer picker takes ages to connect so users get impatient. Apple needs to work on getting this more reliable.
I have restored my ipods now so will be interested to see the outcome.