Is it possible to get the information on the location mode which the user has selected among the three modes under the location settings options i.e
1.Hight Accuracy
2.Battery Saving
3.GPS Only
I want to programmatically check if user has selected High Accuracy mode if not then enable it automatically. Is it possible ? Please advice.
It is possible to get the device's current location mode since API level 19 (Kitkat):
public int getLocationMode(Context context) {
return Settings.Secure.getInt(activityUnderTest.getContentResolver(), Settings.Secure.LOCATION_MODE);
}
These are the possible return values (see here):
0 = LOCATION_MODE_OFF
1 = LOCATION_MODE_SENSORS_ONLY
2 = LOCATION_MODE_BATTERY_SAVING
3 = LOCATION_MODE_HIGH_ACCURACY
So you want something like
if(getLocationMode(context) == 3) {
// do stuff
}
Unfortunately you can't set the location mode programmatically but you can send the user directly to the settings screen where he can do that:
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
You can provide criteria in the LocationMamager.requestLocationUpdates. As criteria you can provide one of the following values to select the accuracy needed.
Constants
int ACCURACY_COARSE A constant indicating an approximate accuracy requirement
int ACCURACY_FINE A constant indicating a finer location accuracy requirement
int ACCURACY_HIGH a constant indicating a high accuracy requirement - may be used for horizontal, altitude, speed or bearing accuracy.
int ACCURACY_LOW A constant indicating a low location accuracy requirement - may be used for horizontal, altitude, speed or bearing accuracy.
int ACCURACY_MEDIUM A constant indicating a medium accuracy requirement - currently used only for horizontal accuracy.
See
http://developer.android.com/reference/android/location/LocationManager.html#requestLocationUpdates(long, float, android.location.Criteria, android.app.PendingIntent)
Since API level 28, you should use LocationManager.isProviderEnabled() to find out if a specific provider is enabled or not.
Changing the setting programmatically from your app is unfortunately not possible.
Related
There is an Android as well as iOS application that I am working on.
Both the applications use google's PlaceAutocomplete controller to get a location's lat-long. In iOS we get lat-long upto 6 decimal places sometimes 5 also. Where as in android we get more than 6 decimal places. The precision of the same location coordinate for Android and iOS differs.
For example consider location Pune
Android Latlng: 18.520431,73.856744
iOS Latlng: 18.52043,73.856744
So as you can see there is difference between the precision of latitudes of the same location.
Is there a way to avoid this as my application needs comparison of these lat-longs?
You should not rely on the precision of the coordinates to compare them because they can change or, as you experiment, vary between platforms.
Instead, you can set a tolerance to determine if two locations are the same. For example:
float YOUR_TOLERANCE = 1; // 1 meter
if (location.distanceTo(otherLocation) < YOUR_TOLERANCE) {
// Both locations are considered the same
}
In android also there is three type of location :
GPS_PROVIDER
NETWORK_PROVIDER
PASSIVE_PROVIDER
So, as per my coding experience i come to know that if you use :
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, new MyLocationListener());
you will get long precision of decimal like more then 14+ and if you will you use fusion of them with this :
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, my_google_listener);
then you will get 6 to 7 digit of precision. try it !!!
I'm currently integrating a Compass View in our Android and iOS application. As expected, the sensor values are not always perfect. It is not that big of a problem but it would be nice to warn the user if the sensors are inaccurate. So is there any way to figure out if the sensors has low accuracy?
On Android, in the SensorEventListener there is a function onAccuracyChanged(Sensor sensor, int accuracy) in which you can check the accuracy of the device's magnetometer. There are 4 levels of accuracy (See the SensorManager class):
SENSOR_STATUS_ACCURACY_HIGH = 3
SENSOR_STATUS_ACCURACY_MEDIUM = 2
SENSOR_STATUS_ACCURACY_LOW = 1
SENSOR_STATUS_UNRELIABLE = 0
I'm not sure how to do that on ios though.
This information is also available for each SensorEvent received in onSensorChanged.
In iOS, the Sensor accuracy is supplied with each update. A headingAccuracy < 0 means that the value is wrong. If it's > 0, it indicates the maximum deviation between the value and the true value and one can define a threshold.
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
NSLog(#"LocationManager did update Heading with accuracy %g", newHeading.headingAccuracy);
if(newHeading.headingAccuracy < 0) {
NSLog(#"Invalid value!");
} else if(newHeading.headingAccuracy < ACCURACY_THRESHOLD) {
NSLog(#"Too low Accuracy!");
} else {
NSLog(#"Accuracy is good enough to use value");
}
}
This question may a repetition but i am not satisfied with others ,that is why asking again .i have created a simple app to show current location and displayed it on map.But its not accurate.I tested my app within a building and is fetching the nearby road as my current location,But other apps like Myteksi,Grab teksi is showing my company name as current location and its accurate.i dont know why its so.Please help.Code for fetching current location is giving below
protected void gotoCurrentLocation() {
Location currentLocation = mLocationClient.getLastLocation();
if (currentLocation == null) {
Log.d("currentLocation-->>>", "null");
Toast.makeText(this, "Current location isn't available",
Toast.LENGTH_SHORT).show();
} else {
LatLng ll = new LatLng(currentLocation.getLatitude(),
currentLocation.getLongitude());
Log.d("lattitude", currentLocation.getLatitude()+"");
Log.d("longitude", currentLocation.getLongitude()+"");
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(ll,
DEFAULTZOOM);
map.animateCamera(update);
/*String address= service.GetAddress(currentLocation.getLatitude(),
currentLocation.getLongitude());
Log.d("address", address);*/
}
}
please comment if any other codes are needed.
As you said you test the app in indoor location. And you know in indoor locations GPS sensor will not work, According to google's docs:
Although GPS is most accurate, it only works outdoors.
So your location might come from Network Provider using wi-fi or cell-id, which is not enough accurate.
Android's Network Location Provider determines user location using cell tower and Wi-Fi signals, providing location information in a way that works indoors and outdoors.
and you must be aware of that:(when using getLastLocation() )
To get the current location, create a location client, connect it to Location Services, and then call its getLastLocation() method. The return value is the best, most recent location, based on the permissions your app requested and the currently-enabled location sensors.
BUT:
The current location is only maintained while a location client is connected to Location Service. Assuming that no other apps are connected to Location Services, if you disconnect the client and then sometime later call getLastLocation(), the result may be out of date.
and also please take a look at this to learn more about Maintaining a current best estimate:
http://developer.android.com/guide/topics/location/strategies.html#BestEstimate
I hope this information helps. ;)
This is because fetching location is a very complicated task to do. And the native implantation of LocationClient might not be the most accurate.
Consider using one or all the 13 sensors(Table 1) in your device to improve that.
TYPE_ACCELEROMETER Hardware Measures the acceleration force in m/s2 that is applied to a device on all three physical axes (x, y, and z), including the force of gravity. Motion detection (shake, tilt, etc.).
TYPE_AMBIENT_TEMPERATURE Hardware Measures the ambient room temperature in degrees Celsius (°C). See note below. Monitoring air temperatures.
TYPE_GRAVITY Software or Hardware Measures the force of gravity in m/s2 that is applied to a device on all three physical axes (x, y, z). Motion detection (shake, tilt, etc.).
TYPE_GYROSCOPE Hardware Measures a device's rate of rotation in rad/s around each of the three physical axes (x, y, and z). Rotation detection (spin, turn, etc.).
TYPE_LIGHT Hardware Measures the ambient light level (illumination) in lx. Controlling screen brightness.
TYPE_LINEAR_ACCELERATION Software or Hardware Measures the acceleration force in m/s2 that is applied to a device on all three physical axes (x, y, and z), excluding the force of gravity. Monitoring acceleration along a single axis.
TYPE_MAGNETIC_FIELD Hardware Measures the ambient geomagnetic field for all three physical axes (x, y, z) in μT. Creating a compass.
TYPE_ORIENTATION Software Measures degrees of rotation that a device makes around all three physical axes (x, y, z). As of API level 3 you can obtain the inclination matrix and rotation matrix for a device by using the gravity sensor and the geomagnetic field sensor in conjunction with the getRotationMatrix() method. Determining device position.
TYPE_PRESSURE Hardware Measures the ambient air pressure in hPa or mbar. Monitoring air pressure changes.
TYPE_PROXIMITY Hardware Measures the proximity of an object in cm relative to the view screen of a device. This sensor is typically used to determine whether a handset is being held up to a person's ear. Phone position during a call.
TYPE_RELATIVE_HUMIDITY Hardware Measures the relative ambient humidity in percent (%). Monitoring dewpoint, absolute, and relative humidity.
TYPE_ROTATION_VECTOR Software or Hardware Measures the orientation of a device by providing the three elements of the device's rotation vector. Motion detection and rotation detection.
TYPE_TEMPERATURE Hardware Measures the temperature of the device in degrees Celsius (°C). This sensor implementation varies across devices and this sensor was replaced with the
TYPE_AMBIENT_TEMPERATURE sensor in API Level 14 Monitoring temperatures
You might be getting stale location data, as you're using LocationClient.getLastKnownLocation(), which returns the last cached location, not the current one. You could try requesting your own location updates using a LocationListener. To do this, you need to create your own LocationListener and override the default onLocationChanged(Location) behavior. For example:
final LocationListener ll = new LocationListener(){
int i=0;
#Override
public void onLocationChanged(Location loc) {
if(i < 5 && loc.getAccuracy() > 8){
i ++;
return;
}
double lat = loc.getLatitude();
double lon = loc.getLongitude();
double acc = loc.getAccuracy();
}
};
You then need to register the listener using an instance of LocationManager:
final LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
This example will register the listener for whenever the GPS location changes. The actual listener code above waits for at least 5 location changes to help ensure that the final location is accurate (the longer time waited, the more time it will have had to lock-on to satellites), then gets the latitude, longitude, and accuracy from the Location object. There are many other ways that you can setup your listener, but that's the way that I did it in one of my apps. If you Google something like "android location updates", you should find some other good tutorials for it. Good luck!
I am working on an application where I need to get the speed of a car. To get the speed, I know I can use something like double speed =locationB.getSpeed();` however when I am testing, the speed varies between 0.0 and 40 km/h when I am just sitting right behind my laptop not moving at all. In the car, the speed actually comes close to the cars speed, so that shouldn't be a problem.
What would be the best way to check if the device is really moving? I've already tried to get the distance between locationA and locationB and use that with the time it took to get the 2 locations, to get the speed.
double distance = locationA.distanceTo(locationB);
double speed = (distance / time) * 3600 / 1000;
However this seems to be not stable at all, like the getSpeed() method.
Is there a way to only display the speed if the device is moving? And would it be reliable?
Any help is appreciated,
Thanks.
Check the horicontal accuracy attribute of Location.
If it is under 30m you can ignore the location.
If you are sitting on your laptop and get speed = 40km/h (which I never saw in good GPS devices), then look what the hor. accuracy is.
It probably is much over 30m.
In GPS based systems, never ever calculate the speed by positional change in time,
just use the location.getSpeed().
The reason is that the GPS chip internally calculates the speed via physical doppler effect, not via positional change.
While standing still, or at very low speeds this does not work well, so you have to filter out very low speeds, and bad gps signal. (via horicontal accuracy estimate)
I think you should limit the distance between A and B to be a minimum length. Small distances will introduce more error into your speed calculations.
Boolean moving - false;
double distance = locationA.distanceTo(locationB);
double speed = (distance / time) * 3600 / 1000;
if (distance > SOME_THRESHOLD) {
moving = true
}
hi to all
how can i get the speed using the ACCESS_COARSE_LOCATION in android
thank you
Hi are you referring to Location.getSpeed() I believe that is an optional field and probably up to the device to actually support it. First off try this
Criteria criteria = new Criteria();
criteria.setSpeedRequired(true);
LocationProvider[] providers = mLocationManager.getProviders(criteria, false);
if (providers == null || providers.length == 0) {
//Sorry it doesn't do it by default.
}
Luckily Math and Science will help us :) Just calculate the speed as you get updates from your LocationProviders. Make sure to calculate the distance between the lat,longs over times as the difference of the recorded times stamps of two Location updates.
...
onLocationChanged(Location location) {
if (mOldLocation != null) {
float distance = getDistance(mOldLocation, location);
long time = location.getTime() - mOldLocation.getTime();
mSpeed = distance/time;
}
mOldLocation = location;
}
It won't necessarily be greatly accurate (probably really noisy) but it's better to make lemonade than to have rotted fruit ... hopefully this helps. Make sure to only compare deltas across the same provider too. You will probably find yourself tweaking the manual calculation because the devices providers are very diverse and don't guarantee that time always moves forward.
Most likely, you cannot. Location technology that is "coarse" only knows where you are within several hundred meters. Your speed could vary wildly. If you need to know your speed, you will most likely need a "fine" location provider.
Or, better yet, use the Criteria object to stipulate that you need to know the device's speed, and let it guide you to the best provider to use.