I have built an app using location detection to get the current location
I am using LocationManager and LocationLiastener
the app works fine but when I tried to run it on advice without android play service it won't get the current Location and show the following dialog
enter image description here
this is the app link on Github
https://github.com/mostafa-n3ma/Pcm-helper1.0
By checking your code here https://github.com/mostafa-n3ma/Pcm-helper1.0/blob/master/app/build.gradle#L69
Are you sure you are not dependent on the google play service library?
this is the problem
private fun checkDeviceLocationSettingsAndGetLocationUpdates(resolve: Boolean = true) {
val locationRequest = com.google.android.gms.location.LocationRequest.create().apply {
priority = LocationRequest.QUALITY_LOW_POWER
}
val builder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest)
val settingsClint = LocationServices.getSettingsClient(requireActivity())
val locationSettingsResponseTask = settingsClint.checkLocationSettings(builder.build())
locationSettingsResponseTask.addOnFailureListener { exeption ->
if (exeption is ResolvableApiException && resolve) {
try {
startIntentSenderForResult(
exeption.resolution.intentSender,
REQUEST_TURN_DEVICE_LOCATION_ON,
null,
0, 0, 0,
null
)
} catch (sendEx: IntentSender.SendIntentException) {
Log.d(TAG, "Error geting location settings resolution: " + sendEx.message)
}
} else {
Snackbar.make(
this.requireView(),
"Location services must be enabled to use the app", Snackbar.LENGTH_INDEFINITE
).setAction(android.R.string.ok) {
checkDeviceLocationSettingsAndGetLocationUpdates()
}.show()
}
}
locationSettingsResponseTask.addOnCompleteListener {
if (it.isSuccessful) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0.0f, locationListener
)
}
}
}
I am using the google services library to check Location setting if it was enabled or not
if the location is ON the location update request will be triggered
else it will ask the user to enable it and then trigger the location update request
if the services are not available nothing will happen and no location update will be requested
so I will try another way to check the location feature
Related
I am using the following code to get the Lat/Long and display.
labelLatLong.Text = "Checking Lat Long. Please wait...";
var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(15));
CancellationTokenSource cts = new CancellationTokenSource();
try
{
var location = Geolocation.GetLocationAsync(request, cts.Token);
if (location != null)
{
labelLatLong.Text = $"Latitude: {location.Result.Latitude}, Longitude: {location.Result.Longitude}, Altitude: {location.Result.Altitude}";
}
}
catch {
labelLatLong.Text = "Unable to get location.";
}
For some reason, I am not getting the location value and there is no exception thrown and I cannot debug beyond the line 'GetLocationAsync', and the application says "App not responding"
I am using Visual Studio 17.4.3, Pixel 5 (API 33) android emulator.
I already gave permissions 'All the time' in the android emulator.
My laptop also has the location enabled.
Are there any other settings, I should be looking at?
Any suggestions? Appreciate your help. Thank you!
In your xaml.cs:
private async void Button_Clicked(object sender, EventArgs e)
{
try
{
var location = await Geolocation.GetLastKnownLocationAsync();
if (location == null)
{
location = await Geolocation.GetLocationAsync(new GeolocationRequest()
{
DesiredAccuracy = GeolocationAccuracy.High, Timeout = TimeSpan.FromSeconds(30)
});
}
if (location == null)
{
labelLatLong.Text = "Unable to get location.";
}
else
{
labelLatLong.Text = $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}";
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
I have following code which return user current location, but the location is not accurate
lateinit var mFusedLocationClient: FusedLocationProviderClient
override fun onCreateView(...) {....}
#SuppressLint("MissingPermission")
private fun getLastLocation() {
mFusedLocationClient.lastLocation
.addOnCompleteListener(requireActivity()) { task ->
if (task.isSuccessful && task.result != null) {
mLastLocation = task.result
mMap.isMyLocationEnabled = true
val driverLatLng = LatLng(mLastLocation.latitude, mLastLocation.longitude)
markerOptions.position(driverLatLng).title("Your location").icon(
BitmapDescriptorFactory.fromBitmap(
driverIcon()
)
)
mMap.addMarker(markerOptions)
} else {
Log.w("location", "getLastLocation:exception", task.exception)
}
}
}
Questions
How to make current location more accurate
How to make blue circle more small, just to cover around current location pin (marker)?
Question 1)
If you are not requesting the highest accuracy possible you need to set it to this value:
LocationRequest.PRIORITY_HIGH_ACCURACY
This way the provider should use the device GPS if available instead of Wi-Fi/cell towers.
Official docs here. A code sample using high accuracy can be found here.
Question 2)
If I got your question right the circle represents the accuracy of the current location so with a higher precision the circle I suppose that the circle would become smaller. You just have to give it a try with the highest possible accuracy (just be sure that the device's GPS is being used and that it has a good signal)
I am working with location kit, Huawei Location Kit works well when I am in open area, but when I go indoor, it either gets location super late, or gets the location with super low precision.
My Location Request is like below:
//create a fusedLocationProviderClient
fusedLocationProviderClient =
LocationServices.getFusedLocationProviderClient(this);
//create a settingsClient
settingsClient = LocationServices.getSettingsClient(this);
mLocationRequest = new LocationRequest();
// set the interval for location updates, in milliseconds.
mLocationRequest.setInterval(10000);
And My Callback is :
mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult != null) {
List<Location> locations = locationResult.getLocations();
if (!locations.isEmpty()) {
for (Location location : locations) {
Log.i(TAG,"onLocationResult location[Longitude,Latitude,Accuracy]:" + location.getLongitude() + "," + location.getLatitude() + "," + location.getAccuracy());
}
}
}
}
#Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
if (locationAvailability != null) {
boolean flag = locationAvailability.isLocationAvailable();
Log.i(TAG, "onLocationAvailability isLocationAvailable:" + flag);
}
}
Any help appreciated.
Huawei's Location Kit obtains user's location by combining data from multiple sources.
This means that in certain scenarious, data from GPS, base stations, WiFi and Bluetooth are combined to get a more accurate location.
When indoors, data from GPS cannot be obtained and as such, the other sources are needed to determine the user's location.
If a sim card is not inserted, the network location from base stations cannot be obtained either.
So if you experience problems while testing the Location Kit indoors, please ensure that you have entered a sim card into the test device and that the network is available.
Additionally, set your location request priority to the highest level in case you have a low priority settting.
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
Another common reason for failing to obtain the location is because the HMS Core application has not been granted the Location permission.
Go to Settings --> Apps --> Apps --> HMS Core --> Permissions --> Location and check whether the "Allow all the time" option has been selected.
You can also use the SettingsClient to check in runtime if the device that your app is running on has granted this permission to the HMS Core application.
More information can be found in the developer documentation:
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/location-develop-steps-0000001050746143#EN-US_TOPIC_0000001050746143__section149231022103316
I'm looking at writing a location-aware application for Android. My application would periodically make calls to a central server, passing in the current user's location. I don't want to drain the battery, so I've been considering using the Passive Location Provider.
According to the provider description no active polling is performed (hence being labelled "Passive"). Instead, it relies on other applications requesting active polls.
My question is: If no other applications poll for Location, does it mean the Passive provider never provides any data? Or, does the Android OS itself periodically poll for Location. If so, what is the polling frequency?
Thanks
You can use the Google Play Services Location API. Its fused location provider will relieve you from such concerns. Forget about which providers to use, or how often the location is polled, or if there are other apps polling. Instead, specify high-level needs like "high accuracy" or "low power", and at which interval your app should be notified. Use listeners or intents to receive location updates from the location service. Here's a more recent article with some code.
AFAIK Android OS will not poll for location itself. If some apps polls it you can received the location then. See Android - Are there query-able services that already poll for GPS location? .
If no app has polled for location from a long time, last location known might be returned by the passive provider. If your application relies heavily on the location, then you might actually want to poll it yourself or if nothing is returned by the passive provider then you can yourself get the location. Frequency of getting the location can be 5 minutes( which is suggested by Google in the Android documentation). This frequency can vary based on your app's requirement.
Is you read the android documentation of requestLocationUpdates of LocationManager, it says:
Choosing a sensible value for minTime is important to conserve battery life. Each location update requires power from GPS, WIFI, Cell and other radios. Select a minTime value as high as possible while still providing a reasonable user experience. If your application is not in the foreground and showing location to the user then your application should avoid using an active provider (such as NETWORK_PROVIDER or GPS_PROVIDER), but if you insist then select a minTime of 5 * 60 * 1000 (5 minutes) or greater. If your application is in the foreground and showing location to the user then it is appropriate to select a faster update interval.
That's my 2 cents regarding your question.
Android devices themselves never poll for users location, you need to do it yourself or rely on other apps to do it for you. You can possibly run the location update every 'x' min, using a GPS or network provider whatever deems fit (or maybe even both !)
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1500000, 0, locationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1500000, 0, locationListener);
If you want to wait for other applications, or not want to drain the battery/search for users exact location you may use locationManager.getLastLocation();
This wont be always accurate, however it is the best you can hope for without actually running a location search
Though I don't believe that PASSIVE_LOCATION PROVIDERS will not get any location unless no other apps get a location, this is some post which is evangelizing it.
I believe that there would be some resident services part of the OS itself which listen to location changed events. because location services without maps, generally use GPS. But I recommend you to have a look at this discussion (probably trusted source).
as none of the posts here answer the OP question i'll make my three words here -
IT'S UP TO PROVIDER (TO PROVIDE THE LOCATION UPDATES) THUS PROVIDER DECIDES HOW OFTEN WILL REPORT THE LOCATION CHANGES TO LOCATON SERVICE
PASIVE - LIKE A PING PONG - to understand what it mean study flow of bellow methods
getLastLocation(LocationRequest request, String packageName)
reportLocation(Location location, boolean passive) -> updateLastLocationLocked(...) -> handleLocationChangedLocked(...)
ITS DEVELOPER JOB TO FILTER AND DECIDE IF PROVIDED LOCATION FULFILLS IT NEEDS
ad 3/ see all location provied details like:
PROVIDER NAME
ACCURACY,
TIME (MILLIS - EPOCH TIME),
SYSTEM ELAPSED NANOS (ELAPSED NANOS FROM DEVICE START)
ADDITIONAL DATA (EG IN BUNDLE LIKE SATELITES COUNT)
ETC...
ad 2/ LOCATION SERVICE IMPLEMENTATION ON AOSP:
package com.android.server;
/**
* The service class that manages LocationProviders and issues location
* updates and alerts.
*/
public class LocationManagerService extends ILocationManager.Stub {
...
// mapping from provider name to last known location
private final HashMap<String, Location> mLastLocation = new HashMap<>();
// same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
// locations stored here are not fudged for coarse permissions.
private final HashMap<String, Location> mLastLocationCoarseInterval = new HashMap<>();
...
#Override
public Location getLastLocation(LocationRequest request, String packageName) {
...
// Figure out the provider. Either its explicitly request (deprecated API's),
// or use the fused provider
String name = request.getProvider();
if (name == null) name = LocationManager.FUSED_PROVIDER;
LocationProviderInterface provider = mProvidersByName.get(name);
if (provider == null) return null;
...
Location location;
if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
// Make sure that an app with coarse permissions can't get frequent location
// updates by calling LocationManager.getLastKnownLocation repeatedly.
location = mLastLocationCoarseInterval.get(name);
} else {
location = mLastLocation.get(name);
}
if (location == null) {
return null;
}
if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
if (noGPSLocation != null) {
return new Location(mLocationFudger.getOrCreate(noGPSLocation));
}
} else {
return new Location(location);
}
}
return null;
....
private void handleLocationChangedLocked(Location location, boolean passive) {
if (D) Log.d(TAG, "incoming location: " + location);
long now = SystemClock.elapsedRealtime();
String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
// Skip if the provider is unknown.
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) return;
updateLastLocationLocked(location, provider);
// mLastLocation should have been updated from the updateLastLocationLocked call above.
Location lastLocation = mLastLocation.get(provider);
if (lastLocation == null) {
Log.e(TAG, "handleLocationChangedLocked() updateLastLocation failed");
return;
}
// Update last known coarse interval location if enough time has passed.
Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
if (lastLocationCoarseInterval == null) {
lastLocationCoarseInterval = new Location(location);
mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
}
long timeDiffNanos = location.getElapsedRealtimeNanos()
- lastLocationCoarseInterval.getElapsedRealtimeNanos();
if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
lastLocationCoarseInterval.set(location);
}
// Don't ever return a coarse location that is more recent than the allowed update
// interval (i.e. don't allow an app to keep registering and unregistering for
// location updates to overcome the minimum interval).
Location noGPSLocation =
lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
// Skip if there are no UpdateRecords for this provider.
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records == null || records.size() == 0) return;
// Fetch coarse location
Location coarseLocation = null;
if (noGPSLocation != null) {
coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
}
// Fetch latest status update time
long newStatusUpdateTime = p.getStatusUpdateTime();
// Get latest status
Bundle extras = new Bundle();
int status = p.getStatus(extras);
ArrayList<Receiver> deadReceivers = null;
ArrayList<UpdateRecord> deadUpdateRecords = null;
// Broadcast location or status to all listeners
for (UpdateRecord r : records) {
...
}
...
}
/**
* Updates last location with the given location
*
* #param location new location to update
* #param provider Location provider to update for
*/
private void updateLastLocationLocked(Location location, String provider) {
Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
Location lastNoGPSLocation;
Location lastLocation = mLastLocation.get(provider);
if (lastLocation == null) {
lastLocation = new Location(provider);
mLastLocation.put(provider, lastLocation);
} else {
lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
if (noGPSLocation == null && lastNoGPSLocation != null) {
// New location has no no-GPS location: adopt last no-GPS location. This is set
// directly into location because we do not want to notify COARSE clients.
location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
}
}
lastLocation.set(location);
}
}
PASIVE PROVIDER:
/**
* A passive location provider reports locations received from other providers
* for clients that want to listen passively without actually triggering
* location updates.
*
* {#hide}
*/
public class PassiveProvider implements LocationProviderInterface {
...
#Override
public void setRequest(ProviderRequest request, WorkSource source) {
mReportLocation = request.reportLocation;
}
public void updateLocation(Location location) {
if (mReportLocation) {
try {
// pass the location back to the location manager
mLocationManager.reportLocation(location, true);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling reportLocation");
}
}
}
...
}
I've asked a question about Commonware's location poller before and got it to work before. Its still working but there is a problem.
Yesterday, (after a bit of experimenting and code studying lol) I realized that in order to get location using both options (prefer GPS, but if not available use Network) I had to pass the extra as 'BOTH'.
After doing that however, the LocationPollerService doesn't FORCE the GPS to locate me. Let me describe the issue below.
Suppose I have my GPS on, and another app actively using the GPS and maintaining a lock. Now, if I use the LocationPollerService, it will return me the value from GPS. However, when my GPS in on, but isn't locked, LocationPollerService doesn't attempt a lock but merely moves on to Network-based Location which isn't what I need when I have GPS enabled.
I would've added code here but I believe this is question specific to cwac-locpoll and the code is already online.
Here's the link:
Commonware's Location Poller
My question? How do I force the service to attempt a location fix when GPS is on?
Update
Here's where I think it looks for GPS location but doesn't actually attempt one. If you could help, that would be great.
#Override protected void onPreExecute()
{
// Added in enabled check to even check if there is a provider
// enabled.
if (provider.equalsIgnoreCase("BOTH"))
{
if (!locMgr.isProviderEnabled(LocationManager.GPS_PROVIDER) && !locMgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
{
Log.i(TAG, "Both providers are disabled");
// There is no provider so fail with the LKL if possible
Intent toBroadcast = new Intent(intentTemplate);
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR, "Location Provider disabled!");
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR_PROVIDER_DISABLED, true);
Location lastLoc = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastLoc == null)
lastLoc = locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
toBroadcast.putExtra(LocationPoller.EXTRA_LASTKNOWN, lastLoc);
sendBroadcast(toBroadcast);
quit();
return;
}
}
else if (!locMgr.isProviderEnabled(provider))
{
Log.i(TAG, provider + " is disabled");
// There is no provider so fail with the LKL if possible
Intent toBroadcast = new Intent(intentTemplate);
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR, "Location Provider disabled!");
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR_PROVIDER_DISABLED, true);
toBroadcast.putExtra(LocationPoller.EXTRA_LASTKNOWN, locMgr.getLastKnownLocation(provider));
sendBroadcast(toBroadcast);
quit();
return;
}
onTimeout = new Runnable()
{
public void run()
{
Intent toBroadcast = new Intent(intentTemplate);
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR, "Timeout!");
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR_PROVIDER_DISABLED, false);
Location lastLoc = null;
if (provider.equalsIgnoreCase("BOTH"))
{
Log.i(TAG, "Both provider timed out");
lastLoc = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastLoc == null)
lastLoc = locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
else
{
Log.i(TAG, provider + " timed out");
lastLoc = locMgr.getLastKnownLocation(provider);
}
toBroadcast.putExtra(LocationPoller.EXTRA_LASTKNOWN, lastLoc);
sendBroadcast(toBroadcast);
quit();
}
};
handler.postDelayed(onTimeout, TIMEOUT);
try
{
Log.e(TAG, "Provider: " + provider);
if (provider.equalsIgnoreCase("BOTH"))
{
Log.i(TAG, "Adding both providers");
locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
locMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
}
else
{
locMgr.requestLocationUpdates(provider, 0, 0, listener);
}
}
catch (IllegalArgumentException e)
{
// see http://code.google.com/p/android/issues/detail?id=21237
Log.w(TAG, "Exception requesting updates -- may be emulator issue", e);
quit();
}
}