I would like to make an app that accepts click events from two real-world buttons. Imagine two-player Flappy Bird that is controlled by a button you can hold.
I will be using CoreBluetooth for this project and Bluetooth Low Energy (BLE, "Bluetooth Smart"). Documented here https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/AboutCoreBluetooth/Introduction.html#//apple_ref/doc/uid/TP40013257-CH1-SW1
Is there a preferred type of physical device and bluetooth device profile I should be considering in choosing the button to use in conjunction with this app?
The standard set of BT4.0 services are listed here
The HID service is probably the closest to the device your are describing, but this is probably more complicated than you need for two buttons. I would just define my own service and characteristics to represent the button status.
It also depends on the hardware you are using to implement the peripheral. There are a number of off-the-shelf BLE devices that present a "serial port" via a couple of attributes. You could use one of these and simply send characters that report the up/down status of the buttons.
Related
As a little holiday project I want to control an app via an accessibility switch which is connected via 3,5mm headphone jack to the iOS device.
This is the switch and the plug:
My problem is that I don't have any clue what kind of signal is fired when I press the button - I assumed that it acts similar to a headphone's remote control.
Is there a way to measure the input of this or does anybody know how to get the input of the button on iOS?
Your button is a "Big Buddy Button Switch," designed by AbleNet for persons with moderate to severe upper extremity and motor disabilities. It is not designed to plug into an IOS device nor into any mobile tablet or phone.
There is an "Hook + Switch" interface ($185 at this moment) that is designed to go between this button and an IOS device, allowing connection of two such buttons to the lightning connector. When connected in this way, the button press can be detected and mapped to many different kinds of IOS actions using apple accessibility settings. That's a lot of money, but since new iphones don't even have audio jacks it may end up being worth it.
A link to your button is here.
A link to the Hook+ Switch Interface is here.
A link to Apple information on accessibility switches is here.
The Big Buddy Button is a passive momentary action switch. The mono TS plug attached is connected internally to the momentary action normally open switch, so pressing the switch will short TIP to SLEEVE.
Plugging this TS plug into an ios device designed to receive a TRRS plug will short RING1 and RING2 and SLEEVE together even when the button is not pressed, which will not accomplish anything useful. Pressing the button will further short TIP to RING1 and RING2 and SLEEVE. There is no way to read such a button press from ios internals if the TS plug is plugged in directly.
If you want to hack together a solution that will work for many mobile devices (e.g., android) you can do so simply by replacing the TS plug with a TRRS plug (or wiring up an adaptor) as follows:
One of the two Big Button conductors should be connected to the SLEEVE, which carries power (for a microphone) and is the source of the voltage that is sensed internally for volume changes and switching. The other Big Button conductor should be connected to RING2, which is the ground line for both earbud channels and the microphone. Nothing should be connected to TIP or RING1.
Pressing the Big Button will momentarily short Sleeve to Ring2, which is the same as pressing the switch on an earbud cable. If you wanted to simulate a volume up or volume down command, you would connect a resistor in series with the button (220 ohms for volume down, 600 ohms for volume up).
The electrical connections for the audio jack are the same for iOS devices as for Android, but there's an extra hurdle you must get over if you want to connect up buttons and have them be detected within iOS. As part of their MFI (Made for iPod/iPhone) program, Apple uses a startup recognition chirp sequence when anything is plugged into the audio jack (or the lightning connector). Your device must have the correct chip inside it (or emulate the behavior of that chip) or else the button controls interface will be disabled when you fail to respond to the authentication request. The protocol seems to have changed over time, because aftermarket products that worked with one model of phone did not always work with another. Apple insiders have stated that the MFI chips contain a serial number that Apple can read upon connection. They say that reverse-engineered authentication works today, but that Apple could prevent it from working at any time.
If you want to design this as a product, you can apply for the MFI program here.
If you just want to build a handful of devices, you won't be able to get accepted into the MFI program. In that case you'd need to purchase the Hook + Switch interface (or something like it) or else you'd need to add a small microprocessor like an Arduino or a Teensy to emulate the authentication chirp, as David Carne did here.
If you just want to build one working button, the easiest way would be to use an existing pair of headphones that contain the necessary chip, and simply put your button wires in parallel with SLEEVE and RING2. If I were doing this I'd get a TRRS extension cord and splice the Big Buddy Button wires to the correct two wires of the extension cord. Your Big Button should work so long as a pair of apple-certified headphones are plugged into the extension to provide the authentication. You would then detect the button press as usual (described here).
EDIT: I tested connecting an accessory button to SLEEVE and RING2 of a TRRS extension cable that's plugged into the iPhone, and as long as a functioning headset is
plugged into the extension cable, the accessory button does work. This way the
accessory button ends up in parallel to the built-in button, without
having to cut apart the headset.
There are other alternatives you could pursue. For example, you could build a circuit that transmits a mic-level tone across the two conductors whenever the button is pressed. You'd then plug that signal into the iOS device between SLEEVE and RING2, and then write an iOS program to listen for the sound and treat it as a button press. MFI authentication would not be needed for this approach, and there are existing utilities that would get you 90% of the way there. You can find an example here.
It's also possible to connect to iOS through BLE without signing up for MFI, and since Apple Accessibility includes the ability to use a bluetooth device to control certain iOS functions, you may be able to do this without needing authentication.
An image showing the connection schematic for TRRS connectors on most mobile devices (including iPhone) is here.
Reproduced here for convenience.
Function/Mic == SLEEVE
Common/Gnd == RING2
Right/R+ == RING1
Left/L+ == TIP
If it was as headphone jack, you can handle it using
override func remoteControlReceived(with event: UIEvent?) {}
and toggle inside of it event?.type.subType something like this.
override func remoteControlReceived(with event: UIEvent?) {
if let e = event , e.type == .remoteControl {
if e.subtype == UIEventSubtype.remoteControlPause {
// do something
}else if(e.subtype == .remoteControlPlay){
//do something else
}else if(e.subtype == .remoteControlTogglePlayPause){
// do something else
}
}
}
Apples wired 3.5 mm headphone with volume control have 4 conductors. In your picture I see only 2 conductors. So your switch can't be sending the Apples's own headphone remote commands - since the the microphone ring for sending data is missing.
I'd guess your switch just makes contact between the two conductors.
Here is what I would do.
Verify with a multi meter the resistance of your switch in the open and closed position.
I'd expect on close the resistance is low or close to zero.
Now find an (old) pair of Apple 3.5 mm headphones with volume control. Disassemble the volume control of the headphones and solder your accessibility switch to the volume control pads. Now your accessibility switch simulates pushing the volume control.
Alternatively look at http://david.carne.ca/shuffle_hax/shuffle_remote.html
So use a micro controller to simulate the headphone volume control and use your accessibility switch to control the micro controller. It looks like a fun project - enjoy.
I am trying to navigate the user to Bluetooth settings on a button click. CBCentralManager(delegate: self, queue: nil) works fine when Bluetooth is turned off from Settings App, but it is not working when Bluetooth is turned off from Control center e.g not showing the default Bluetooth popup.
Now I need to know if Bluetooth is turned off from the Control center so that I can show some custom popup message to the user.
Any help will be appreciated.
You are correct that the initialization option CBCentralManagerOptionShowPowerAlertKey, which should display a warning if the framework is initiated when bluetooth is turned off, does in fact not work as expected if bluetooth is toggled off from the Control Center. Since iOS 11 the system will actually not turn off bluetooth if you toggle off the button in Control Center, it only disconnects currently connected devices. The only way to turn off bluetooth then is to do it from System Settings. This is documented by Apple, but to me it is extremely misleading. So I honestly don't know if the API behavior you are experiencing is a bug, or if it is expected behavior.
My suggestion is that you skip this initialization option and instead rely on the value of central.state when you get the "centralManagerDidUpdateState:" callback and then create you own popup if the value is CBManagerStatePoweredOff, which oddly enough will be the case regardless if bluetooth is turned off from System Settings or if it is toggled off from the Control Center.
If your app works in the background you may want to use a local notification instead to get your user's attention.
Not a perfect solution, but it should be more reliable.
I have filed bug report 47516284 with Apple for this problem. Here's the text of the issue I filed.
I have noticed that the system alert notifying a user that an app needs Bluetooth will show when I turn off Bluetooth using the Settings app. I can use this system alert to go directly to bluetooth settings to turn it back on. However, when I turn off Bluetooth using Control center, there is no system alert that displays. This is problematic because although I can display a custom alert to tell the user to turn on Bluetooth, there is no way to code bringing the user directly to Bluetooth settings by tapping a button for instance. I believe the functionality should be consistent no matter how the user turns off Bluetooth.
There are two approaches for showing an app/app suggestion (incase not installed) on the iphone lock screen / app switcher. One is GPS based, in which the IOS decides which app to show as a suggestion. Another is beacon based, in which a particular beacon is identified.
If location services are enabled for multiple apps and say all these apps are also using beacon based approach to show their icons on the lock screen left corner, which app icon will be shown by the IOS?
Since location services are enabled for these apps,and say there is another relevant app which is NOT using beacon based approach (using just the GPS based approach), can IOS give preference to beacon based apps over the GPS based this new app.?
For instance, Estimote’s NYC office is on the same block as an Equinox gym and our phones intelligently and automatically alert us to use that app. It’s super easy and intuitive to open the app while walking into the gym - and in the process, streamline the check-in flow with the gym’s front desk. However, because it solely uses GPS geofences, the accuracy is poor. We actually get the Equinox icon over 1 block away, and there is no control for the brands or stores (in this case Equinox) on how this appears.
Apple's suggestion of apps not installed on the phone based on proximity uses an undocumented technique. While I have verified it uses GPS as an input, I have never been able to confirm that beacons are used at all.
Regardless of whether beacons are used, because this is an undocumented feature, it is unlikely you will find a way to customize the behavior.
AFAIK, Apple has never shared the implementation details of how the lock screen icon AKA "suggested apps" feature works.
However, we did some experiments at Estimote and noticed that being inside a CLRegion (both the "GPS" CLCircularRegion, and CLBeaconRegion work) that an app monitors for via Core Location, consistently makes the app's icon show up on the lock screen. So it seems that both beacons and GPS location fall into the same mechanism that governs the location-based suggestions. (Note that in iOS 9, that's not just the lock screen icon, but also a bar at the bottom of the app switcher.)
Unfortunately, we weren't able to establish what happens if you're inside multiple qualifying CLRegions, belonging to different apps. We suspect it might have something to do with the order in which the apps register regions for monitoring, but were never able to get consistent results.
Furthermore, since this whole behavior is undocumented, Apple can change it at any time. Just something to be aware of.
Side note: handoff always trumps suggested apps.
Has Apple documented any means (such as a UIRequiredDeviceCapabilities key) for requiring 3D Touch on a device?
Am looking into things that will need 3D Touch. Wouldn't be the best experience to run an alert telling the user their new app won't work...
Thanks in advance.
In my opinion you might not even see 3D Touch having a key in UIRequiredDeviceCapabilities. If that happens, it should be in a relatively long time until it is considered absolutely essential.
You should look at 3D Touch as a nice to have, not a mandatory capability.
If it enables certain features on your app, you need to make sure you have a fallback mechanism to access them when the capability is nonexistent.
Moreover, Users with a 3D Touch capable device can disable the feature in:
Settings > General > Accessibility > 3D Touch
So you should always code for both scenarios.
Think of it more like TouchID rather than like Metal. Even though nowadays almost everyone has an iOS device capable of using fingerprint scanning, people can still disable it and use a passcode. So if your app uses TouchID (e.g. most banking apps, Evernote, 1Password, etc) you still need a fallback.
Source: Accessibility and Human Interface Guidelines for 3D Touch
To ensure that all your users can access your app’s features, branch your code depending on whether 3D Touch is available. See Checking for 3D Touch Availability.
NOTE
3D Touch is available only on 3D Touch devices and when enabled. In iOS 9, 3D Touch is enabled by default. A user can turn off 3D Touch in Settings > General > Accessibility > 3D Touch.
When 3D Touch is available, take advantage of its capabilities. When it is not available, provide alternatives such as by employing touch and hold.
UIRequiredDeviceCapabilities is currently the only way to prevent customers from installing apps on a device that does not support certain capabilities by limiting them from installing from the App Store.
As of the time of this posting there is no key for 3D Touch, so your best option would probably be either putting it in the app description somewhere obvious, or as a warning in-app as you mentioned.
Hopefully they will add this key in the future, but I would assume that Apple's preferred usage of 3D touch is as a complementary but not necessary feature in iOS apps.
Even though there is no 3D Touch in UIRequiredDeviceCapabilities, the iPhone 6S and 6S Plus are the only iPhones to have 2 GB of RAM, the rest have at most 1 GB. So just make your app run on iPhones only and require 2 GB of RAM.
I also have a case that I want to show a menu tab for only 3DTouch devices.
For now, if a device without 3DTouch (EG iphone5) upgrades to iOS9.0, it will have 3DTouch enabled by default. When you read the value from traitCollection.forceTouchCapability, it tells you UIForceTouchCapabilityUnavailable. If you have a device with 3DTouch (which will also use iOS9), the value is UIForceTouchCapabilityAvailable.
One other option is to use a third party class to know what device you are using. If it is iPhone6S or iPhone6S+, then return true for supporting3DTouch. But you have to manually update future iOS devices.
I am writing a checkin app that will use a bluetooth RFID scanner to checkin users as they scan. All the scanners that I've found seem to work as bluetooth keyboards. The issue is that there will be other activity going on in the app including typing using the built in keyboard. I want this activity to be uninterrupted by the RFID scanner. So my idea is to check as every character comes in wether it is coming from the built in keyboard or the bluetooth one and if it is from the bluetooth scanner move that to a hidden textfield to be dealt with on a separate thread while the user can continue typing. Is there any way that I can do this?