Can I find out whether the user is driving? - ios

I am writing an app for iOS.
I want to know the user's current motion type, for example, walking, driving running. In particular I am interested in knowing whether they are driving.
I would also like to detect when the device connects to a car Bluetooth, as this may also indicate that they are driving.

While your app is active you can use CMMotionActivityManager to get the current motion type.
Note that it won't tell you whether the person is driving or a passenger or even in another vehicle that has similar motion characteristics, such as a train. You can't get motion activity updates while your app is suspended.
You could combine it with Signification Location updates to get periodic execution in the background.
This answer has some suggestions on detecting Bluetooth HFP devices by checking the available audio input devices. Note that you can't check this in the background and you can't get a "notification" that a HFP has connected unless you are actively inputting or outputting audio - You would need to check periodically

Related

CLLocationManager region monitoring and airplane mode

I am developing a location dependent feature. The uses case is this:
User receives data and notifications based on their location.
Location is actually the city/town they reside in more accurately a
region based on the city.
Then they hop on a plane/train and go to another city. I want to
be able to detect that send them local notification to change
their location settings and if they accept to start providing them
data based on the new location i.e. city. Very important to this
part of the usage is the Airplane mode which is usually turned on
during the travel and then turned off when the user arrives at
their destination.
I thought region monitoring will be the perfect technology for that. However there is no way to find out if the user had gone outside the region when using Airplane mode. There will be nor crossing event and I am unable to request the state for the particular region. Also in that case if the app was terminated the system will not wake it up for crossing event because there is not one.
Is there a way to reliably handle that situation.
I also thought a replacement technology for my use case might be the Visit monitoring.
Thanks!

change output speaker when user move his phone

My app lets the user hear sound files, and im using AVAudioPlayer to play it.
I saw in some apps a very nice behaviour where the sound speakers changes from regular speakers to the ear speakers when the user put his phone next to his ear.
I have now idea where to start here, should i detect the phone's movement and change the output speaker or is there any native implementation for this behaviour?
The most straightforward path to accomplishing this is to use proximity monitoring in UIDevice. Proximity monitoring tells you whether the phone is close to the user or not.
Listen for UIDeviceOrientationDidChangeNotification and react to proximityState changes accordingly — in your case, rerouting audio.
There's a thorough answer to a similar question here. That answer includes supplementary details to combine device motion for increased accuracy.
What you're looking for is the proximity sensor (that little piece of hardware near the iphone ear speaker), and not any motion sensing mechanism. The proximity sensor is accessible via the public API through the UIDevice's proximityState property, which simply returns a boolean value indicating whether the sensor is close to the user or not: proximityState.
Based on that value, you can then proceed to routing your audio to the ear speaker. This can be achieved using the AVAudioSession class and specifically setting the category (setCategory:error) to AVAudioSessionCategoryPlayAndRecord.

How can I capture the accelerometer data on iPhone when the app is in background?

In an iOS app, by enabling the flags for VOIP, Audio playback, Location, Bluetooth LE accessories, News stand etc, we can run the app in background. But I've a requirement to create a library/framework that will make the app run in background as well as capture the accelerometer updates and log them to a file.
For that purpose, I enabled "Audio Playback" in the background, and playing a silent file in continuous loop so that app will continue to run in background. At the same time, I'm able to capture the accelerometer data as well. I'm using Core Motion framework for the same and its working perfect.
I would like to add one more point, my app has location tracking enabled to deal with beacons integration.
I want to know if its valid to follow such procedure and will Apple approve it during the review process? Has any one faced this kind of challenge ever?
As you guessed, the only way to access accelerometer data in background is with an active background mode. But...
Apple will NEVER accept your app if it declares a background mode without any feature actually using it (not just technically like your silent sound, but an actual feature that your user is aware of)
If you decide to implement a feature that actually use a background mode (like location or audio playback for example), don't forget that you will also drain your user's battery.
Conclusion:
Explain to your client that Apple's restrictions prevent you to do that and have the requirements updated
or
Find another feature that will need to use one of the background modes

In ios, is it possible to know if the GPS location is not being updated?

I'm creating an app that allows the user to navigate with a map when offline (no internet connection or wifi available), and I want to let the user know if the gps location not being updated. I know I can get the last updated location timestamp and the accuracy, but is it possible to know if the gps has no reception?
No, there's no public interface for finding out about the state of specific location hardware such as the GPS receiver.
The Location Manager abstracts all that away, so that developers can get location and accuracy information without worrying about whether the device used GPS, Wifi, iBeacons, cell tower locations, Loran-C, celestial navigation, etc. to determine the location. This is generally a very good thing because it means that your apps work on all devices regardless of whether they have GPS, and will continue to work (and maybe even work better) on new devices that might use other technology. But it also means that you don't get to ask the question "is the device receiving a GPS signal right now?"
Is it possible to know if the GPS location is not being updated?
No. It doesn't seem possible given the available API.
There are a few things about GPS to consider, if you haven't already. It is technically possible to receive a location update from CLLocationManager when you're "offline" but it will depend on several things:
If your device actually has GPS hardware. Some don't.
If you have line of sight to GPS satellites. There's a difference between GPS and A-GPS
Those true GPS updates will come much less frequently because of the way GPS works, but it should work.
... but is it possible to know if the gps has no reception
Based on the way GPS works (as best I understand it) you either turn the radio on/off (-startUpdatingLocation/-stopUpdatingLocation) with the Location Services API and you either get locations more frequently with A-GPS or infrequently with pure GPS when you don't have a network signal. I don't think the Location Services API has a way of telling you "I don't have a GPS signal at all."

iOS: detect app users nearby

I want to build and app which can detect other iPhones with my app within 65 feet range. As I understand I have the following choices:
Use Bluetooth to check periodically whether there is device with my app in the range. Send list of found devices to the server. The problem here is battery consumption. Is it true that Bluetooth will be disabled after some period of time automatically?
Can I use BLE technology for this purpose? If so, do you know what devices support BLE?
What is the best option on your opinion? Did I miss some other option?
Thanks
UPDATE
I plan to run search every 20 seconds or even more often.
There is no simple answer to this problem.
Bluetooth has 2 flavors: "Regular" bluetooth, used for hands-free devices, headphones, and the like, and BLE (Bluetooth Low Energy)
Regular bluetooth devices must be paired. (I'm less familiar with regular bluetooth than BLE, so take my explanation of this bit with a grain of salt.) In order to be paired they have to be put into "discoverable" mode, which broadcasts their ID. That is a battery-draining and only done briefly. It's not an "always on" solution.
BLE has a range of up to 60 meters, so it should meet your need in that regard.
BLE devices can "advertise" as a "peripheral" for extended periods. Other Bluetooth devices can act as a "central" and ask to be notified when certain peripheral devices are detected. I'm not sure if you can make an iOS device advertise (broadcast) as a BLE peripheral while it's in the background and/or if the device is locked, but it will certainly advertise while it's running. I'm pretty sure you can register to be notified when you detect a certain BLE peripheral from the background, but not positive.
iBeacons are a specific use of BLE with some extra limitations and some extra abilities. An iBeacon is a dirt-simple transmitter that sends a UUID plus a major and minor value and a signal strength calibration value periodically (usually once a second.) You can't add any other data to an iBeacon transmission. iOS can only act as an iBeacon transmitter when the app is in the foreground. If your app moves to the background, it stops transmitting. Period.
However, you can listen for iBeacon signals even from the background. AND, if you've registered as a listener for an iBeacon and the system terminates your app due to low memory, the system still listens for those beacons on your behalf. If iOS detects a beacon you're listening for, you get re-launched if needed, and notified in the background. You can then post a local notification to get the user's attention.
iBeacons are probably your best bet, but you will need your users to be actively running your app in the foreground in order to transmit a signal. That will drain your user's battery fairly quickly.
One possible solution would to have have every single device send their locations to your server every predetermined time period (more frequent the better but more resource intensive). Then, query the data from the server and get the location of all the devices near you.
Keep in mind, that this probably won't be very useful for real-time data collection. For example, if you want to send data every 30 seconds or so, this isn't a good option.
Use this option if you want to get data every 15-20 minutes or so.

Resources