Get Altitude, Bearing, speed and GPS Accuracy - ios

Hy guys, i need to find altitude, bearing and gps accuracy in my iPhone app. i've done this on my android app. in android, i did it like this :
public void onLocationChanged(Location location) {
if (isBetterLocation(location, lastValidLocation)
&& isEnable) {
lastValidLocation = location;
longitude = location.getLongitude();
latitude = location.getLatitude();
altitude = location.getAltitude();
speed = location.getSpeed();
accuracy = location.getAccuracy();
bearing = location.getBearing();
locationProvider = location.getProvider();
onPositionChanged(
LocationService.this,
new GeoPoint(location.getLongitude(), location
.getLatitude()));
}
}
how can i do the same thing in iOS ?
i've tried to get it from CLLocation, but it return null/0,0000/-1.0000 ..
btw, i get this result when i test it on iOS Simulator.
Thanks.
Regards.

The simulator is not a good place to test Core Location stuff. It only simulates a specific location but if you want to test speed, bearing etc. you're better of trying on a real device.
You need to use the class CLLocationManager (Apple doc) and fetch the data using the delegate protocol available. For example, if you want the heading you implement the method locationManager:didUpdateHeading: and call the method startUpdatingHeading on the location manager.

Related

Get distance from eddystone beacon

I am implementing beacons in my app with google beacon platform. Currently, beacon can be detected from a long range. I need to limit the range of detection which is quite not possible right now. Other option I am considering to detect the distance between iPhone and beacon. Is there anything provided by google or open-source SDK which can help me achieving the desired behaviour?
The documentation is pretty sparse, but I have open source code here detecting Eddystone on iOS and ranging beacons with it.
Here is an example of how you use it to detect Eddystone-UID:
var scanner: RNLBeaconScanner?
scanner = RNLBeaconScanner.shared()
scanner?.startScanning()
// Execute this code periodically (every second or so) to view the beacons detected
if let detectedBeacons = scanner?.trackedBeacons() as? [RNLBeacon] {
for beacon in detectedBeacons {
if (beacon.beaconTypeCode.intValue == 0x00 && beacon.serviceUuid.intValue == 0xFEAA) {
// this is eddystone uid
NSLog("Detected EDDYSTONE-UID with namespace %# instance %#", beacon.id1, beacon.id2)
NSLog("The beacon is about %.1f meters away", beacon.distance)
}
}
}

How to detect iBeacons without know UUID,Any Possible to get core bluetooth or Some other way

Is it possible to detect iBeacons without knowing their UUID?
Is there any way to use Core Bluetooth or some other method?
You must know at least the UUID you are looking for in order to create a CLBeaconRegion. There is no way on iOS to scan for "all beacons".
iBeacons are specifically obscured from Core Bluetooth discovery.
While you cannot detect beacons on iOS without specifying the ProximityUUID up front, you can set up ranging to look for a large number of ProximityUUIDs -- I have successfully ranged for 100 of them at the same time (although 1000 crashes my app.)
By using an online beacon database, you can find a list of UUIDs known to be close to you. This won't detect every beacon for sure, but it will allow you to detect many that are around you without having to build the UUIDs into your app.
Here's an example using the NingoSDK to get the 100 nearest ProximityUUIDs to your location and register them for ranging.
let locationManager = CLLocationManager()
// Get up to 100 beacon ProximityUUIDs within 1km from our current location, so we can use these for beacon ranging
let queryClient = QueryBeaconClient(authToken: Settings().getSetting(key: Settings.ningoReadonlyApiTokenKey)!)
queryClient.queryFirstIdentifiers(latitude: latitude, longitude: longitude, radiusMeters: 1000, limit: 100) { (proximityUUIDStrings, errorCode, errorDetail) in
if let proximityUUIDStrings = proximityUUIDStrings {
NSLog("There are now \(proximityUUIDStrings.count) nearby beacon uuids")
if proximityUUIDStrings.count > 0 {
for region in locationManager.rangedRegions {
locationManager.stopRangingBeacons(in: region as! CLBeaconRegion)
}
for uuidString in proximityUUIDStrings {
let region = CLBeaconRegion(proximityUUID: UUID(uuidString: uuidString)!, identifier: uuidString)
locationManager.startRangingBeacons(in: region)
}
BeaconTracker.shared.updateTransientUuids(uuids: proximityUUIDStrings)
}
}
}

Set location simulator City/GPX during Runtime

Is there a method to programmatically change the location simulator city during runtime? For example this would allow tests to simulate London or Tokyo.
The image below shows how to switch between locations (GPX files) manually. How can I achieve this result programmatically while the app is running?
Alternate way to set location is by swizzling 'location' of 'CLLocationManager' class. In obj-c,
+(void) load {
// replace 'location' with 'custom_location' method
}
Then implement custom_location method with whatever the location you want to set by simply changing 'kMockedLatitude' and 'kMockedLongitude' variables.
//Portland, USA
CLLocationDegrees kMockedLatitude = 45.52306;
CLLocationDegrees kMockedLongitude = -122.67648;
-(CLLocation *)custom_location
{
return [[CLLocation alloc] initWithLatitude:kMockedLatitude longitude:kMockedLongitude];
}
This will work even in iOS device.

CLLocationManager always returning speed: -1

I'm trying to determine the location of my users and I have everything setup properly but my devices return -1 for speed and course all the time. When I run the exact same setup on the simulator speed and course values are just fine.
I have calibrated the compass on my test devices and the maps show the correct locations. I have also reset location and privacy settings and I have used 5 different phones. It's always the same story on all devices.
manager = [[CLLocationManager alloc] init];
self.manager.delegate = self;
manager.desiredAccuracy = kCLLocationAccuracyBest;
manager.distanceFilter = 500;
manager.activityType = CLActivityTypeOther;
[manager startUpdatingLocation];
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
for (CLLocation *location in locations) {
//double speed = 0.0;
//speed = location.speed;
//NSLog(#"%f", s);
NSLog(#"%#", location.description);
}
}
This returns this:
2015-05-07 12:16:57.703 Health_[323:84932] Location: (
"<+52.55719238,+11.02049967> +/- 165.00m (speed -1.00 mps / course -1.00) # 07.05.15 12:16:57 Mitteleurop\U00e4ische Sommerzeit"
)
Does anyone have an idea what's going on?
As it turns out CLLocationManager does not return any speed or course information if you
a. don't move at all. A fixed location always has -1 values (should return something else in my opinion but oh well).
b. haven't let the location manager run for a little while. If you stop the location manager immediately after you have created and started it, it does not yet know any of these information (again should return something different in my opinion then "invalid value").
In my case I was doing both of these things and as it turns out none of my devices are broken... (phew)
I made a little application and put it on Github to help others understand this problem. Just put it on your phone and move around for a little while. It will eventually return something but just not immediately and not if you don't move and haven't moved in a while.

Geolocation giving weird position sometimes

var initialLocation;
var siberia = new google.maps.LatLng(60, 105);
var newyork = new google.maps.LatLng(40.69847032728747, -73.9514422416687);
var browserSupportFlag = new Boolean(); // Try W3C Geolocation (Preferred)
if (navigator.geolocation) {
browserSupportFlag = true;
navigator.geolocation.getCurrentPosition(function(position) {
initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude); // THERES OUR LAT/LONG VALUES
ajaxPost(initialLocation);
},
function() {
handleNoGeolocation(browserSupportFlag);
}); // Try Google Gears Geolocation
} else if (google.gears) {
browserSupportFlag = true;
var geo = google.gears.factory.create('beta.geolocation');
geo.getCurrentPosition(function(position) {
initialLocation = new google.maps.LatLng(position.latitude, position.longitude); // THERES OUR LAT/LONG VALUES
ajaxPost(initialLocation);
},
function() {
handleNoGeoLocation(browserSupportFlag);
}); // Browser doesn't support Geolocation
} else {
browserSupportFlag = false;
handleNoGeolocation(browserSupportFlag);
}
function handleNoGeolocation(errorFlag) {
if (errorFlag == true) {
initialLocation = new google.maps.LatLng(geoip_latitude(), geoip_longitude()); // THERES OUR LAT/LONG VALUES
ajaxPost(initialLocation);
navigator.notification.alert('Geolocation service failed', // message
'Geolocation Error!', // title
'OK' // buttonName
);
} else {
initialLocation = new google.maps.LatLng(geoip_latitude(), geoip_longitude()); // THERES OUR LAT/LONG VALUES
ajaxPost(initialLocation);
navigator.notification.alert("Your browser doesn't support geolocation. We've placed you in Siberia.", // message
'Browser Error!', // title
'OK' // buttonName
);
} // THERES OUR LAT/LONG VALUES
}
This is code we use in our Sencha Touch application to get the users current position. Now, I tested this code using a 3G connection on my Droid HTC Eris, and it gave me a location 6 miles away from myself, which is fine, I can live with that, I could probably even live with a little bit more.
However, testing on an iPod Touch using Wifi, connecting to our in home router, it put us 147 miles from our current location. Now, this might make sense if our router here had some weird IP address or something like that (w/e this code actually uses to find location if it doesn't fall back to IP), but I testing geolocation straight from google from a laptop also hooked up to our wifi here and it puts us less than 1 mile from overhead.
What kind of situation could make this happen? Is this something we are just going to have to live with until geolocation further advances? If so, that's fine, I just want to know if there's something we could do to improve this. 147 miles away is a little crazy, considering every other source we've tried puts us within 10 max.
The only thing I can think of is that google has some correction listings in it's own databases. What is probably happening is your ip is registered to a holdco which is 147 miles away from you. For example if whois my IP it is registered to a holding company which is about 50 miles away from me. Non-corrected databases (such as the ones you typically buy online) show me in that town. Google, whoever does not.

Resources