L'API LocationManager
sur Android semble être un peu difficile à utiliser pour une application qui nécessite seulement une approximation approximative et approximative de l'emplacement de l'utilisateur.
L'application sur laquelle je travaille n'est pas vraiment une application de localisation en tant que telle, mais elle doit obtenir l'emplacement de l'utilisateur pour afficher une liste des entreprises à proximité. Il n'est pas nécessaire de s'inquiéter de savoir si l'utilisateur se déplace ou quelque chose comme ça.
Voici ce que j'aimerais faire:
Activity
X, il sera disponible.Il semble que cela ne devrait pas être si difficile, mais il me semble que je dois activer deux fournisseurs d’emplacement différents (GPS et NETWORK) et gérer leur cycle de vie. Non seulement cela, mais je dois dupliquer le même code dans plusieurs activités pour satisfaire # 2. Dans le passé, j’ai essayé d’utiliser getBestProvider()
pour réduire la solution à un seul fournisseur, mais cela ne semble vous donner que le meilleur fournisseur "théorique" plutôt que le fournisseur qui va réellement vous donner les meilleurs résultats.
Y a-t-il un moyen plus simple d'y parvenir?
Voici ce que je fais:
Voici comment j'utilise ma classe:
LocationResult locationResult = new LocationResult(){
@Override
public void gotLocation(Location location){
//Got the location!
}
};
MyLocation myLocation = new MyLocation();
myLocation.getLocation(this, locationResult);
Et voici la classe MyLocation:
import Java.util.Timer;
import Java.util.TimerTask;
import Android.content.Context;
import Android.location.Location;
import Android.location.LocationListener;
import Android.location.LocationManager;
import Android.os.Bundle;
public class MyLocation {
Timer timer1;
LocationManager lm;
LocationResult locationResult;
boolean gps_enabled=false;
boolean network_enabled=false;
public boolean getLocation(Context context, LocationResult result)
{
//I use LocationResult callback class to pass location value from MyLocation to user code.
locationResult=result;
if(lm==null)
lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//exceptions will be thrown if provider is not permitted.
try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){}
try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){}
//don't start listeners if no provider is enabled
if(!gps_enabled && !network_enabled)
return false;
if(gps_enabled)
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
if(network_enabled)
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
timer1=new Timer();
timer1.schedule(new GetLastLocation(), 20000);
return true;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerNetwork);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
locationResult.gotLocation(location);
lm.removeUpdates(this);
lm.removeUpdates(locationListenerGps);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
class GetLastLocation extends TimerTask {
@Override
public void run() {
lm.removeUpdates(locationListenerGps);
lm.removeUpdates(locationListenerNetwork);
Location net_loc=null, gps_loc=null;
if(gps_enabled)
gps_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(network_enabled)
net_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//if there are both values use the latest one
if(gps_loc!=null && net_loc!=null){
if(gps_loc.getTime()>net_loc.getTime())
locationResult.gotLocation(gps_loc);
else
locationResult.gotLocation(net_loc);
return;
}
if(gps_loc!=null){
locationResult.gotLocation(gps_loc);
return;
}
if(net_loc!=null){
locationResult.gotLocation(net_loc);
return;
}
locationResult.gotLocation(null);
}
}
public static abstract class LocationResult{
public abstract void gotLocation(Location location);
}
}
Quelqu'un peut aussi vouloir modifier ma logique. Par exemple, si vous obtenez une mise à jour du fournisseur de réseau, n'arrêtez pas les écouteurs mais continuez d'attendre. Le GPS fournit des données plus précises, il vaut donc la peine de les attendre. Si le délai est écoulé et que vous disposez d'une mise à jour du réseau mais pas du GPS, vous pouvez utiliser la valeur fournie par le réseau.
Une autre approche consiste à utiliser LocationClient http://developer.Android.com/training/location/retrieve-current.html . Mais il faut que Google Play Services apk soit installé sur la machine de l'utilisateur.
Après avoir recherché la meilleure implémentation pour obtenir la meilleure localisation précise possible, j'ai réussi à combiner toutes les meilleures méthodes et à proposer la classe suivante:
/**
* Retrieve accurate location from GPS or network services.
*
*
* Class usage example:
*
* public void onCreate(Bundle savedInstanceState) {
* ...
* my_location = new MyLocation();
* my_location.init(main.this, locationResult);
* }
*
*
* public LocationResult locationResult = new LocationResult(){
* @Override
* public void gotLocation(final Location location){
* // do something
* location.getLongitude();
* location.getLatitude();
* }
* };
*/
class MyLocation{
/**
* If GPS is enabled.
* Use minimal connected satellites count.
*/
private static final int min_gps_sat_count = 5;
/**
* Iteration step time.
*/
private static final int iteration_timeout_step = 500;
LocationResult locationResult;
private Location bestLocation = null;
private Handler handler = new Handler();
private LocationManager myLocationManager;
public Context context;
private boolean gps_enabled = false;
private int counts = 0;
private int sat_count = 0;
private Runnable showTime = new Runnable() {
public void run() {
boolean stop = false;
counts++;
System.println("counts=" + counts);
//if timeout (1 min) exceeded, stop tying
if(counts > 120){
stop = true;
}
//update last best location
bestLocation = getLocation(context);
//if location is not ready or don`t exists, try again
if(bestLocation == null && gps_enabled){
System.println("BestLocation not ready, continue to wait");
handler.postDelayed(this, iteration_timeout_step);
}else{
//if best location is known, calculate if we need to continue to look for better location
//if gps is enabled and min satellites count has not been connected or min check count is smaller then 4 (2 sec)
if(stop == false && !needToStop()){
System.println("Connected " + sat_count + " sattelites. continue waiting..");
handler.postDelayed(this, iteration_timeout_step);
}else{
System.println("#########################################");
System.println("BestLocation finded return result to main. sat_count=" + sat_count);
System.println("#########################################");
// removing all updates and listeners
myLocationManager.removeUpdates(gpsLocationListener);
myLocationManager.removeUpdates(networkLocationListener);
myLocationManager.removeGpsStatusListener(gpsStatusListener);
sat_count = 0;
// send best location to locationResult
locationResult.gotLocation(bestLocation);
}
}
}
};
/**
* Determine if continue to try to find best location
*/
private Boolean needToStop(){
if(!gps_enabled){
return true;
}
else if(counts <= 4){
return false;
}
if(sat_count < min_gps_sat_count){
//if 20-25 sec and 3 satellites found then stop
if(counts >= 40 && sat_count >= 3){
return true;
}
return false;
}
}
return true;
}
/**
* Best location abstract result class
*/
public static abstract class LocationResult{
public abstract void gotLocation(Location location);
}
/**
* Initialize starting values and starting best location listeners
*
* @param Context ctx
* @param LocationResult result
*/
public void init(Context ctx, LocationResult result){
context = ctx;
locationResult = result;
myLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
gps_enabled = (Boolean) myLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
bestLocation = null;
counts = 0;
// turning on location updates
myLocationManager.requestLocationUpdates("network", 0, 0, networkLocationListener);
myLocationManager.requestLocationUpdates("gps", 0, 0, gpsLocationListener);
myLocationManager.addGpsStatusListener(gpsStatusListener);
// starting best location Finder loop
handler.postDelayed(showTime, iteration_timeout_step);
}
/**
* GpsStatus listener. OnChainged counts connected satellites count.
*/
public final GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() {
public void onGpsStatusChanged(int event) {
if(event == GpsStatus.GPS_EVENT_SATELLITE_STATUS){
try {
// Check number of satellites in list to determine fix state
GpsStatus status = myLocationManager.getGpsStatus(null);
Iterable<GpsSatellite>satellites = status.getSatellites();
sat_count = 0;
Iterator<GpsSatellite>satI = satellites.iterator();
while(satI.hasNext()) {
GpsSatellite satellite = satI.next();
System.println("Satellite: snr=" + satellite.getSnr() + ", elevation=" + satellite.getElevation());
sat_count++;
}
} catch (Exception e) {
e.printStackTrace();
sat_count = min_gps_sat_count + 1;
}
System.println("#### sat_count = " + sat_count);
}
}
};
/**
* Gps location listener.
*/
public final LocationListener gpsLocationListener = new LocationListener(){
@Override
public void onLocationChanged(Location location){
}
public void onProviderDisabled(String provider){}
public void onProviderEnabled(String provider){}
public void onStatusChanged(String provider, int status, Bundle extras){}
};
/**
* Network location listener.
*/
public final LocationListener networkLocationListener = new LocationListener(){
@Override
public void onLocationChanged(Location location){
}
public void onProviderDisabled(String provider){}
public void onProviderEnabled(String provider){}
public void onStatusChanged(String provider, int status, Bundle extras){}
};
/**
* Returns best location using LocationManager.getBestProvider()
*
* @param context
* @return Location|null
*/
public static Location getLocation(Context context){
System.println("getLocation()");
// fetch last known location and update it
try {
LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
String strLocationProvider = lm.getBestProvider(criteria, true);
System.println("strLocationProvider=" + strLocationProvider);
Location location = lm.getLastKnownLocation(strLocationProvider);
if(location != null){
return location;
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Cette classe tente de se connecter aux satellites min_gps_sat_count
si le GPS est activé. Sinon, retourne LocationManager.getBestProvider()
location. Vérifiez le code!
Avec la solution de Fedor, j'ai connu plusieurs exécutions du callback gotLocation
. Cela semble être dû à une condition de concurrence dans la méthode LocationListener.onLocationChanged
remplacée, lorsque la méthode gotLocation est 'assez longue' . Je ne suis pas sûr, mais je suppose que removeUpdates
empêche la mise en file d'attente de nouveaux messages dans la file d'attente Looper, mais cela ne supprime pas ceux déjà mis en file d'attente mais pas encore consommés. D'où la condition de concurrence.
Pour réduire le risque de ce problème, il est possible d'appeler removeUpdates avant de déclencher l'événement onLocationChanged, mais la condition de concurrence est toujours remplie.
La meilleure solution que j'ai trouvée consiste à remplacer requestLocationUpdates
par requestSingleUpdate
.
Voici ma version, basée sur la solution de Fedor, qui utilise un gestionnaire pour envoyer un message au thread Looper:
public class LocationResolver {
private Timer timer;
private LocationManager locationManager;
private LocationResult locationResult;
private boolean gpsEnabled = false;
private boolean networkEnabled = false;
private Handler locationTimeoutHandler;
private final Callback locationTimeoutCallback = new Callback() {
public boolean handleMessage(Message msg) {
locationTimeoutFunc();
return true;
}
private void locationTimeoutFunc() {
locationManager.removeUpdates(locationListenerGps);
locationManager.removeUpdates(locationListenerNetwork);
Location networkLocation = null, gpsLocation = null;
if (gpsEnabled)
gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (networkEnabled)
networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
// if there are both values use the latest one
if (gpsLocation != null && networkLocation != null) {
if (gpsLocation.getTime() > networkLocation.getTime())
locationResult.gotLocation(gpsLocation);
else
locationResult.gotLocation(networkLocation);
return;
}
if (gpsLocation != null) {
locationResult.gotLocation(gpsLocation);
return;
}
if (networkLocation != null) {
locationResult.gotLocation(networkLocation);
return;
}
locationResult.gotLocation(null);
}
};
private final LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer.cancel();
locationResult.gotLocation(location);
locationManager.removeUpdates(this);
locationManager.removeUpdates(locationListenerNetwork);
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
private final LocationListener locationListenerNetwork = new LocationListener() {
public void onLocationChanged(Location location) {
timer.cancel();
locationResult.gotLocation(location);
locationManager.removeUpdates(this);
locationManager.removeUpdates(locationListenerGps);
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) {
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
public void prepare() {
locationTimeoutHandler = new Handler(locationTimeoutCallback);
}
public synchronized boolean getLocation(Context context, LocationResult result, int maxMillisToWait) {
locationResult = result;
if (locationManager == null)
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
// exceptions will be thrown if provider is not permitted.
try {
gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
try {
networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
// don't start listeners if no provider is enabled
if (!gpsEnabled && !networkEnabled)
return false;
if (gpsEnabled)
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, locationListenerGps, Looper.myLooper());
//locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
if (networkEnabled)
locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER, locationListenerNetwork, Looper.myLooper());
//locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
timer = new Timer();
timer.schedule(new GetLastLocationTask(), maxMillisToWait);
return true;
}
private class GetLastLocationTask extends TimerTask {
@Override
public void run() {
locationTimeoutHandler.sendEmptyMessage(0);
}
}
public static abstract class LocationResult {
public abstract void gotLocation(Location location);
}
}
J'utilise cette classe à partir d'un thread de boucleur personnalisé, comme le suivant:
public class LocationGetter {
private final Context context;
private Location location = null;
private final Object gotLocationLock = new Object();
private final LocationResult locationResult = new LocationResult() {
@Override
public void gotLocation(Location location) {
synchronized (gotLocationLock) {
LocationGetter.this.location = location;
gotLocationLock.notifyAll();
Looper.myLooper().quit();
}
}
};
public LocationGetter(Context context) {
if (context == null)
throw new IllegalArgumentException("context == null");
this.context = context;
}
public synchronized Coordinates getLocation(int maxWaitingTime, int updateTimeout) {
try {
final int updateTimeoutPar = updateTimeout;
synchronized (gotLocationLock) {
new Thread() {
public void run() {
Looper.prepare();
LocationResolver locationResolver = new LocationResolver();
locationResolver.prepare();
locationResolver.getLocation(context, locationResult, updateTimeoutPar);
Looper.loop();
}
}.start();
gotLocationLock.wait(maxWaitingTime);
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
if (location != null)
coordinates = new Coordinates(location.getLatitude(), location.getLongitude());
else
coordinates = Coordinates.UNDEFINED;
return coordinates;
}
}
où Coordinates est une classe simple avec deux propriétés: latitude et longitude.
J'ai créé une petite application avec une description étape par étape pour obtenir les coordonnées GPS des emplacements actuels.
Exemple de code source complet dans l'URL ci-dessous:
Obtenir les coordonnées géographiques actuelles, Nom de la ville - sous Android
Regarde comment ça marche :
Tout ce que nous avons à faire est d’ajouter cette permission dans le fichier manifeste
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION">
</uses-permission>
et créer une instance LocationManager comme celle-ci
LocationManager locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
Vérifier que le GPS est activé ou non
puis implémenter LocationListener et obtenir les coordonnées
LocationListener locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
voici l'exemple de code à faire
/*----------Listener class to get coordinates ------------- */
private class MyLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location loc) {
editLocation.setText("");
pb.setVisibility(View.INVISIBLE);
Toast.makeText(
getBaseContext(),
"Location changed: Lat: " + loc.getLatitude() + " Lng: "
+ loc.getLongitude(), Toast.LENGTH_SHORT).show();
String longitude = "Longitude: " + loc.getLongitude();
Log.v(TAG, longitude);
String latitude = "Latitude: " + loc.getLatitude();
Log.v(TAG, latitude);
/*-------to get City-Name from coordinates -------- */
String cityName = null;
Geocoder gcd = new Geocoder(getBaseContext(), Locale.getDefault());
List<Address> addresses;
try {
addresses = gcd.getFromLocation(loc.getLatitude(),
loc.getLongitude(), 1);
if (addresses.size() > 0)
System.out.println(addresses.get(0).getLocality());
cityName = addresses.get(0).getLocality();
} catch (IOException e) {
e.printStackTrace();
}
String s = longitude + "\n" + latitude + "\n\nMy Current City is: "
+ cityName;
editLocation.setText(s);
}
@Override
public void onProviderDisabled(String provider) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
Vous pouvez toujours simplement utiliser LocationManager.getLastKnownLocation () mais comme il est dit, il pourrait être périmé.
Et un moyen simple d'obtenir un emplacement général pourrait être de vous inscrire au réseau (généralement assez rapidement).
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 1000, 1000, this);
et ensuite faire
locationManager.removeUpdates(this);
dans la méthode onLocationChanged()
de l'auditeur.
J'ai écrit un tutoriel détaillé couvrant l'emplacement actuel ici sur demonuts.com . Vous pouvez trouver plus de description ici et aussi vous pouvez télécharger le code source complet de démonstration pour une meilleure compréhension.
Il y a déjà beaucoup de réponses ici mais je veux montrer la dernière méthode pour obtenir un emplacement en utilisant Google API, afin que les nouveaux programmeurs puissent utiliser une nouvelle méthode:
Tout d’abord, mettez ceci dans un fichier de classement
compile 'com.google.Android.gms:play-services:8.4.0'
puis implémenter les interfaces nécessaires
public class MainActivity extends BaseActivitiy implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.Android.gms.location.LocationListener
déclarer des instances
private GoogleApiClient mGoogleApiClient;
private Location mLocation;
private LocationManager locationManager;
private LocationRequest mLocationRequest;
mettre ceci dans onCreate()
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Enfin, remplacez les méthodes nécessaires
@Override
public void onConnected(Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(mLocation == null){
startLocationUpdates();
}
if (mLocation != null) {
double latitude = mLocation.getLatitude();
double longitude = mLocation.getLongitude();
} else {
// Toast.makeText(this, "Location not Detected", Toast.LENGTH_SHORT).show();
}
}
protected void startLocationUpdates() {
// Create the location request
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
// Request location updates
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
Log.d("reque", "--->>>>");
}
@Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connection Suspended");
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed. Error: " + connectionResult.getErrorCode());
}
@Override
public void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
public void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
@Override
public void onLocationChanged(Location location) {
}
N'oubliez pas de démarrer le GPS sur votre appareil avant de lancer l'application.
Utilisez le code ci-dessous, cela donnera le meilleur fournisseur disponible:
String locCtx = Context.LOCATION_SERVICE;
LocationManager locationMgr = (LocationManager) ctx.getSystemService(locCtx);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
String provider = locationMgr.getBestProvider(criteria, true);
System.out.println("Best Available provider::::"+provider);
Je ne sais pas si les Services basés sur la localisation peuvent obtenir la localisation d'autres infrastructures que le GPS, mais selon cet article, il semble possible:
Les applications peuvent faire appel à n’importe lequel des fichiers plusieurs types de méthodes de positionnement.
Utilisation du réseau de téléphonie mobile: Le l'identifiant de cellule actuel peut être utilisé pour identifier la station émettrice-réceptrice de base (BTS) que le périphérique communique avec et l'emplacement de ce BTS . Clairement, la précision de cette méthode dépend de la taille de la cellule, et peut être assez inexact. Une cellule GSM peut être n'importe où de 2 à 20 kilomètres de diamètre. Autre les techniques utilisées avec l'identifiant de cellule peuvent atteindre une précision dans les 150 mètres.
Utilisation de satellites: The Global Système de positionnement (GPS), contrôlé par le département américain de la Défense, utilise une constellation de 24 satellites en orbite autour de la terre. Le GPS détermine le la position de l'appareil en calculant les différences dans les signaux horaires de différents satellites prennent pour atteindre le receveur. Les signaux GPS sont codés, donc l'appareil mobile doit être équipé avec un récepteur GPS. Le GPS est potentiellement la méthode la plus précise (entre 4 et 40 mètres si le récepteur GPS a une vue dégagée du ciel), mais il a quelques inconvénients: Le supplément le matériel peut être coûteux, consomme batterie en cours d’utilisation, et nécessite un peu d'échauffement après un démarrage à froid pour obtenir un repère initial sur les satellites visibles . Il souffre également des "effets de canyon" dans les villes, où la visibilité par satellite est intermittent.
Utilisation à courte portée Balises de positionnement: En relativement petites zones, comme un seul bâtiment, un réseau local peut fournir des emplacements avec d’autres prestations de service. Par exemple, de manière appropriée Les appareils équipés peuvent utiliser Bluetooth pour positionnement à courte portée.
En fait, nous pouvons utiliser les deux fournisseurs (GPS et réseau). Et ils partagent juste un auditeur public:
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10 * 1000, (float) 10.0, listener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 90 * 1000, (float) 10.0, listener);
Cela est nécessaire car la méthode OnLocationChanged()
doit toujours être appelée à temps.
La méthode recommandée consiste à utiliser LocationClient
:
Tout d’abord, définissez les valeurs de l’intervalle de mise à jour de la localisation. Adaptez-le à vos besoins.
private static final int MILLISECONDS_PER_SECOND = 1000;
private static final long UPDATE_INTERVAL = MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
private static final int FASTEST_INTERVAL_IN_SECONDS = 1;
private static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
Demandez à votre Activity
d'implémenter GooglePlayServicesClient.ConnectionCallbacks
, GooglePlayServicesClient.OnConnectionFailedListener
et LocationListener
.
public class LocationActivity extends Activity implements
GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {}
Ensuite, configurez une LocationClient
dans la méthode onCreate()
de votre Activity
:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLocationClient = new LocationClient(this, this, this);
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
}
Ajoutez les méthodes requises à votre Activity
; onConnected()
est la méthode appelée lorsque LocationClient
connects. onLocationChanged()
est l'endroit où vous récupérez l'emplacement le plus récent.
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.w(TAG, "Location client connection failed");
}
@Override
public void onConnected(Bundle dataBundle) {
Log.d(TAG, "Location client connected");
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
@Override
public void onDisconnected() {
Log.d(TAG, "Location client disconnected");
}
@Override
public void onLocationChanged(Location location) {
if (location != null) {
Log.d(TAG, "Updated Location: " + Double.toString(location.getLatitude()) + "," + Double.toString(location.getLongitude()));
} else {
Log.d(TAG, "Updated location NULL");
}
}
Assurez-vous de connecter/déconnecter la LocationClient
afin d’utiliser uniquement une batterie supplémentaire lorsque cela est absolument nécessaire et pour que le GPS ne fonctionne pas indéfiniment. La LocationClient
doit être connectée pour pouvoir en extraire des données.
public void onResume() {
super.onResume();
mLocationClient.connect();
}
public void onStop() {
if (mLocationClient.isConnected()) {
mLocationClient.removeLocationUpdates(this);
}
mLocationClient.disconnect();
super.onStop();
}
Obtenir l'emplacement de l'utilisateur. Commencez par utiliser la variable LocationClient
; si cela échoue, retournez à la LocationManager
.
public Location getLocation() {
if (mLocationClient != null && mLocationClient.isConnected()) {
return mLocationClient.getLastLocation();
} else {
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (locationManager != null) {
Location lastKnownLocationGPS = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKnownLocationGPS != null) {
return lastKnownLocationGPS;
} else {
return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
} else {
return null;
}
}
}
C'est le code qui fournit l'emplacement actuel de l'utilisateur
créer des cartes Activty:
public class Maps extends MapActivity {
public static final String TAG = "MapActivity";
private MapView mapView;
private LocationManager locationManager;
Geocoder geocoder;
Location location;
LocationListener locationListener;
CountDownTimer locationtimer;
MapController mapController;
MapOverlay mapOverlay = new MapOverlay();
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
initComponents();
mapView.setBuiltInZoomControls(true);
mapView.setSatellite(true);
mapView.setTraffic(true);
mapView.setStreetView(true);
mapController = mapView.getController();
mapController.setZoom(16);
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (locationManager == null) {
Toast.makeText(Maps.this, "Location Manager Not Available",
Toast.LENGTH_SHORT).show();
return;
}
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location == null)
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
double lat = location.getLatitude();
double lng = location.getLongitude();
Toast.makeText(Maps.this, "Location Are" + lat + ":" + lng,
Toast.LENGTH_SHORT).show();
GeoPoint point = new GeoPoint((int) (lat * 1E6), (int) (lng * 1E6));
mapController.animateTo(point, new Message());
mapOverlay.setPointToDraw(point);
List<Overlay> listOfOverlays = mapView.getOverlays();
listOfOverlays.clear();
listOfOverlays.add(mapOverlay);
}
locationListener = new LocationListener() {
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {}
public void onProviderEnabled(String arg0) {}
public void onProviderDisabled(String arg0) {}
public void onLocationChanged(Location l) {
location = l;
locationManager.removeUpdates(this);
if (l.getLatitude() == 0 || l.getLongitude() == 0) {
} else {
double lat = l.getLatitude();
double lng = l.getLongitude();
Toast.makeText(Maps.this, "Location Are" + lat + ":" + lng,
Toast.LENGTH_SHORT).show();
}
}
};
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 1000, 10f, locationListener);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 1000, 10f, locationListener);
locationtimer = new CountDownTimer(30000, 5000) {
@Override
public void onTick(long millisUntilFinished) {
if (location != null) locationtimer.cancel();
}
@Override
public void onFinish() {
if (location == null) {
}
}
};
locationtimer.start();
}
public MapView getMapView() {
return this.mapView;
}
private void initComponents() {
mapView = (MapView) findViewById(R.id.map_container);
ImageView ivhome = (ImageView) this.findViewById(R.id.imageView_home);
ivhome.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent intent = new Intent(Maps.this, GridViewContainer.class);
startActivity(intent);
finish();
}
});
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
class MapOverlay extends Overlay {
private GeoPoint pointToDraw;
public void setPointToDraw(GeoPoint point) {
pointToDraw = point;
}
public GeoPoint getPointToDraw() {
return pointToDraw;
}
@Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
long when) {
super.draw(canvas, mapView, shadow);
Point screenPts = new Point();
mapView.getProjection().toPixels(pointToDraw, screenPts);
Bitmap bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.select_map);
canvas.drawBitmap(bmp, screenPts.x, screenPts.y - 24, null);
return true;
}
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@Android:color/black"
Android:orientation="vertical" >
<com.google.Android.maps.MapView
Android:id="@+id/map_container"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:apiKey="yor api key"
Android:clickable="true"
Android:focusable="true" />
</LinearLayout>
et définir l'autorisation suivante dans le manifeste:
<uses-permission Android:name="Android.permission.INTERNET"/>
<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION"/>
EDIT: mis à jour avec la dernière API de service de localisation de la bibliothèque de services Google Play (juillet 2014).
Je vous recommanderais d'utiliser la nouvelle Location Service API , disponible dans la bibliothèque de services Google Play, qui fournit une infrastructure de niveau supérieur plus puissante qui automatise des tâches telles que le choix du fournisseur d'emplacement et la gestion de l'alimentation. Selon la documentation officielle: "... Les API de localisation facilitent la création d'applications orientées emplacement, sans avoir à se concentrer sur les détails de la technologie de localisation sous-jacente. Elles vous permettent également de réduire la consommation d'énergie en utilisant toutes les fonctionnalités du matériel de l'appareil ".
Pour plus d’informations, rendez-vous sur: Rendre votre application sensible à l’emplacement
Pour voir un exemple complet utilisant la dernière version de l'API de service de localisation, visitez: La classe Android LocationClient est obsolète mais utilisée dans la documentation
Pour obtenir et afficher l'emplacement actuel de l'utilisateur, vous pouvez également utiliser MyLocationOverlay
. Supposons que vous ayez un champ mapView
dans votre activité. Tout ce que vous devez faire pour afficher l'emplacement de l'utilisateur est le suivant:
myLocationOverlay = new MyLocationOverlay(this, mapView);
myLocationOverlay.enableMyLocation();
mapView.getOverlays().add(myLocationOverlay);
Cela permet d'obtenir la position actuelle du GPS ou du réseau. Si les deux échouent, enableMyLocation()
renverra false
.
En ce qui concerne l'emplacement des choses autour de la zone, une ItemizedOverlay
devrait faire l'affaire.
J'espère que je n'ai pas mal compris votre question. Bonne chance.
Même si la réponse est déjà donnée ici. Je voulais juste partager ceci avec le monde au cas où un tel scénario se présenterait.
Mon exigence était que je devais obtenir l'emplacement actuel d'un utilisateur dans un délai maximal de 30 à 35 secondes. Voici donc la solution que j'ai proposée à la suite de Réponse de Nirav Ranpara .
1. J'ai créé la classe MyLocationManager.Java qui gère tout le matériel GPS et réseau.
import Java.util.concurrent.Executors;
import Java.util.concurrent.ScheduledExecutorService;
import Java.util.concurrent.TimeUnit;
import com.app.callbacks.OnLocationDetectectionListener;
import Android.app.AlertDialog;
import Android.content.Context;
import Android.content.DialogInterface;
import Android.content.Intent;
import Android.location.Location;
import Android.location.LocationListener;
import Android.location.LocationManager;
import Android.os.Bundle;
import Android.provider.Settings;
import Android.util.Log;
import Android.widget.Toast;
public class MyLocationManager {
/** The minimum distance to GPS change Updates in meters **/
private final long MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_GPS = 2; // 2
// meters
/** The minimum time between GPS updates in milliseconds **/
private final long MIN_TIME_BW_UPDATES_OF_GPS = 1000 * 5 * 1; // 5
// seconds
/** The minimum distance to NETWORK change Updates in meters **/
private final long MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_NETWORK = 5; // 5
// meters
/** The minimum time between NETWORK updates in milliseconds **/
private final long MIN_TIME_BW_UPDATES_OF_NETWORK = 1000 * 10 * 1; // 10
// seconds
/**
* Lets just say i don't trust the first location that the is found. This is
* to avoid that
**/
private int NetworkLocationCount = 0, GPSLocationCount = 0;
private boolean isGPSEnabled;
private boolean isNetworkEnabled;
/**
* Don't do anything if location is being updated by Network or by GPS
*/
private boolean isLocationManagerBusy;
private LocationManager locationManager;
private Location currentLocation;
private Context mContext;
private OnLocationDetectectionListener mListener;
public MyLocationManager(Context mContext,
OnLocationDetectectionListener mListener) {
this.mContext = mContext;
this.mListener = mListener;
}
/**
* Start the location manager to find my location
*/
public void startLocating() {
try {
locationManager = (LocationManager) mContext
.getSystemService(Context.LOCATION_SERVICE);
// Getting GPS status
isGPSEnabled = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
// Getting network status
isNetworkEnabled = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// No network provider is enabled
showSettingsAlertDialog();
} else {
// If GPS enabled, get latitude/longitude using GPS Services
if (isGPSEnabled) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES_OF_GPS,
MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_GPS,
gpsLocationListener);
}
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES_OF_NETWORK,
MIN_DISTANCE_CHANGE_FOR_UPDATES_FOR_NETWORK,
networkLocationListener);
}
}
/**
* My 30 seconds plan to get myself a location
*/
ScheduledExecutorService se = Executors
.newSingleThreadScheduledExecutor();
se.schedule(new Runnable() {
@Override
public void run() {
if (currentLocation == null) {
if (isGPSEnabled) {
currentLocation = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} else if (isNetworkEnabled) {
currentLocation = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
if (currentLocation != null && mListener != null) {
locationManager.removeUpdates(gpsLocationListener);
locationManager
.removeUpdates(networkLocationListener);
mListener.onLocationDetected(currentLocation);
}
}
}
}, 30, TimeUnit.SECONDS);
} catch (Exception e) {
Log.e("Error Fetching Location", e.getMessage());
Toast.makeText(mContext,
"Error Fetching Location" + e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
/**
* Handle GPS location listener callbacks
*/
private LocationListener gpsLocationListener = new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onLocationChanged(Location location) {
if (GPSLocationCount != 0 && !isLocationManagerBusy) {
Log.d("GPS Enabled", "GPS Enabled");
isLocationManagerBusy = true;
currentLocation = location;
locationManager.removeUpdates(gpsLocationListener);
locationManager.removeUpdates(networkLocationListener);
isLocationManagerBusy = false;
if (currentLocation != null && mListener != null) {
mListener.onLocationDetected(currentLocation);
}
}
GPSLocationCount++;
}
};
/**
* Handle Network location listener callbacks
*/
private LocationListener networkLocationListener = new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onLocationChanged(Location location) {
if (NetworkLocationCount != 0 && !isLocationManagerBusy) {
Log.d("Network", "Network");
isLocationManagerBusy = true;
currentLocation = location;
locationManager.removeUpdates(gpsLocationListener);
locationManager.removeUpdates(networkLocationListener);
isLocationManagerBusy = false;
if (currentLocation != null && mListener != null) {
mListener.onLocationDetected(currentLocation);
}
}
NetworkLocationCount++;
}
};
/**
* Function to show settings alert dialog. On pressing the Settings button
* it will launch Settings Options.
* */
public void showSettingsAlertDialog() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
// Setting Dialog Title
alertDialog.setTitle("GPS is settings");
// Setting Dialog Message
alertDialog
.setMessage("GPS is not enabled. Do you want to go to settings menu?");
// On pressing the Settings button.
alertDialog.setPositiveButton("Settings",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// On pressing the cancel button
alertDialog.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
// Showing Alert Message
alertDialog.show();
}
}
2. J'ai créé une interface (rappel) OnLocationDetectectionListener.Java afin de communiquer les résultats au fragment appelant ou à l'activité
import Android.location.Location;
public interface OnLocationDetectectionListener {
public void onLocationDetected(Location mLocation);
}
3. Ensuite, j'ai créé une activité MainAppActivty.Java qui implémente l'interface OnLocationDetectectionListener
et voici comment je reçois ma position.
public class MainAppActivty extends Activity implements
OnLocationDetectectionListener {
private Location currentLocation;
private MyLocationManager mLocationManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_home);
super.onCreate(savedInstanceState);
mLocationManager = new MyLocationManager(this, this);
mLocationManager.startLocating();
}
@Override
public void onLocationDetected(Location mLocation) {
//Your new Location is received here
currentLocation = mLocation;
}
4. Ajoutez les autorisations suivantes à votre fichier manifeste
<uses-permission Android:name="Android.permission.INTERNET" />
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
J'espère que cela aidera les autres :)
Il faut beaucoup de choses en place pour obtenir des mises à jour de localisation dans Android, il nécessite beaucoup de code bolierplate.
Vous devez prendre soin de
J'ai créé Android-EasyLocation (petite bibliothèque Android) qui prendra soin de tout cela et vous pourrez vous concentrer sur la logique métier.
Tout ce dont vous avez besoin est de prolonger EasyLocationActivity et cela
requestSingleLocationFix(easyLocationRequest);
ou
requestLocationUpdates(easyLocationRequest);
Commander exemple d'application et les étapes nécessaires ici à https://github.com/akhgupta/Android-EasyLocation
Depuis plus d’un an, j’utilisais la combinaison de GPS_PROVIDER et de NETWORK_PROVIDER pour obtenir l’emplacement actuel. Cela fonctionnait bien, mais depuis quelques mois, je l’obtiens après un long délai. ça marche plutôt bien.
Voici la classe que j'ai écrite pour obtenir l'emplacement actuel à l'aide de FusedLocationProviderClient . .
private static FusedLocationService ourInstance;
private final LocationRequest locationRequest;
private FusedLocationProviderClient mFusedLocationClient;
private Location mLastLocation;
private Context context;
private FindOutLocation findOutLocation;
private boolean callbackTriggered = false;
private Timer timer;
public static FusedLocationService getInstance(Context pContext) {
if (null == ourInstance) ourInstance = new FusedLocationService(pContext);
return ourInstance;
}
private FusedLocationService(Context pContext) {
context = pContext;
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
locationRequest = getLocationRequest();
requestLocation(context);
}
public Location getLastKnownLocation() {
return mLastLocation;
}
private void requestLocation(Context context) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mFusedLocationClient.requestLocationUpdates(locationRequest, mLocationCallback, null);
mFusedLocationClient.getLastLocation().addOnSuccessListener(location -> {
if (location != null) {
mLastLocation = location;
triggerCallback(mLastLocation);
}
});
}
private LocationRequest getLocationRequest() {
LocationRequest locationRequest = new LocationRequest();
long INTERVAL = 10 * 1000;
long FASTEST_INTERVAL = 5 * 1000;
locationRequest.setInterval(INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
return locationRequest;
}
private LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
if (location != null) mLastLocation = location;
}
if (null != mLastLocation) triggerCallback(mLastLocation);
}
};
public static abstract class FindOutLocation {
public abstract void gotLocation(Location location);
}
@SuppressLint("MissingPermission")
public void findLocation(FindOutLocation findOutLocation) {
long TIMER_TIME_OUT = 15 * 1000;
this.findOutLocation = findOutLocation;
callbackTriggered = false;
try {
requestLocation(context);
timer = new Timer();
timer.schedule(new GetLastLocation(context), TIMER_TIME_OUT);
} catch (Exception e) {
e.printStackTrace();
}
}
private class GetLastLocation extends TimerTask {
Context context;
GetLastLocation(Context context) {
this.context = context;
}
@Override
public void run() {
triggerCallback(mLastLocation);
}
}
private void triggerCallback(Location location) {
if (null != location) mLastLocation = location;
if (!callbackTriggered && null != findOutLocation) {
callbackTriggered = true;
removeLocationUpdates();
findOutLocation.gotLocation(location);
findOutLocation = null;
}
}
private void removeLocationUpdates() {
if (null != timer) timer.cancel();
if (null != mFusedLocationClient)
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
}
Et appelé cela de l'activité, voici le code
FusedLocationService.FindOutLocation findOutLocation = new FusedLocationService.FindOutLocation() {
@Override
public void gotLocation(Location currentLocation) {
if (currentLocation != null) {
/*TODO DO SOMETHING WITH CURRENT LOCATION*/
}
}
};
FusedLocationService.getInstance(this).findLocation(findOutLocation);
Ajouter les entrées suivantes dans le fichier AndroidManifest.xml
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION" />
<!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
<uses-feature Android:name="Android.hardware.location.gps" />
Simple et le meilleur moyen de géolocalisation.
LocationManager lm = null;
boolean network_enabled;
if (lm == null)
lm = (LocationManager) Kikit.this.getSystemService(Context.LOCATION_SERVICE);
network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
dialog = ProgressDialog.show(Kikit.this, "", "Fetching location...", true);
final Handler handler = new Handler();
timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run()
{
Log.e("counter value","value "+counter);
if(counter<=8)
{
try
{
counter++;
if (network_enabled) {
lm = (LocationManager) Kikit.this.getSystemService(Context.LOCATION_SERVICE);
Log.e("in network_enabled..","in network_enabled");
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener()
{
public void onLocationChanged(Location location)
{
if(attempt == false)
{
attempt = true;
Log.e("in location listener..","in location listener..");
longi = location.getLongitude();
lati = location.getLatitude();
Data.longi = "" + longi;
Data.lati = "" + lati;
Log.e("longitude : ",""+longi);
Log.e("latitude : ",""+lati);
if(faceboo_name.equals(""))
{
if(dialog!=null){
dialog.cancel();}
timer.cancel();
timer.purge();
Data.homepage_resume = true;
lm = null;
Intent intent = new Intent();
intent.setClass(Kikit.this,MainActivity.class);
startActivity(intent);
finish();
}
else
{
isInternetPresent = cd.isConnectingToInternet();
if (isInternetPresent)
{
if(dialog!=null)
dialog.cancel();
Showdata();
}
else
{
error_view.setText(Data.internet_error_msg);
error_view.setVisibility(0);
error_gone();
}
}
}
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
}
public void onProviderEnabled(String provider) {
//Toast.makeText(getApplicationContext(), "Location enabled", Toast.LENGTH_LONG).show();
}
public void onProviderDisabled(String provider) {
}
};
// Register the listener with the Location Manager to receive
// location updates
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100000, 10,locationListener);
} else{
//Toast.makeText(getApplicationContext(), "No Internet Connection.", 2000).show();
buildAlertMessageNoGps();
}
} catch (Exception e) {
// TODO
// Auto-generated
// catch
// block
}
}
else
{
timer.purge();
timer.cancel();
if(attempt == false)
{
attempt = true;
String locationProvider = LocationManager.NETWORK_PROVIDER;
// Or use LocationManager.GPS_PROVIDER
try {
Location lastKnownLocation = lm.getLastKnownLocation(locationProvider);
longi = lastKnownLocation.getLongitude();
lati = lastKnownLocation.getLatitude();
Data.longi = "" + longi;
Data.lati = "" + lati;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.i("exception in loc fetch", e.toString());
}
Log.e("longitude of last known location : ",""+longi);
Log.e("latitude of last known location : ",""+lati);
if(Data.fb_access_token == "")
{
if(dialog!=null){
dialog.cancel();}
timer.cancel();
timer.purge();
Data.homepage_resume = true;
Intent intent = new Intent();
intent.setClass(Kikit.this,MainActivity.class);
startActivity(intent);
finish();
}
else
{
isInternetPresent = cd.isConnectingToInternet();
if (isInternetPresent)
{
if(dialog!=null){
dialog.cancel();}
Showdata();
}
else
{
error_view.setText(Data.internet_error_msg);
error_view.setVisibility(0);
error_gone();
}
}
}
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 2000);
private void buildAlertMessageNoGps() {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Your WiFi & mobile network location is disabled , do you want to enable it?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id)
{
startActivity(new Intent(Android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
setting_page = true;
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
dialog.cancel();
finish();
}
});
final AlertDialog alert = builder.create();
alert.show();
}
Un peu tard ici, mais ce que je voudrais dans une telle situation est d'utiliser l'API Google Maps et de marquer les emplacements à proximité à l'aide des API lat et longue de Google Maps. De plus, l'expérience utilisateur est meilleure si vous pouvez afficher sa position sur une carte. Pas besoin de se soucier de la mise à jour de la localisation de l'utilisateur ou de la recherche avec Android api. Laissez Google Maps gérer les internes pour vous.
@emmby a peut-être résolu le problème dans son application, mais je le recommande aux développeurs de Google Maps pour consulter les API Google Maps.
Edit: Lien pour afficher la localisation de l'utilisateur dans google maps
public static Location getBestLocation(Context ctxt) {
Location gpslocation = getLocationByProvider(
LocationManager.GPS_PROVIDER, ctxt);
Location networkLocation = getLocationByProvider(
LocationManager.NETWORK_PROVIDER, ctxt);
Location fetchedlocation = null;
// if we have only one location available, the choice is easy
if (gpslocation != null) {
Log.i("New Location Receiver", "GPS Location available.");
fetchedlocation = gpslocation;
} else {
Log.i("New Location Receiver",
"No GPS Location available. Fetching Network location lat="
+ networkLocation.getLatitude() + " lon ="
+ networkLocation.getLongitude());
fetchedlocation = networkLocation;
}
return fetchedlocation;
}
/**
* get the last known location from a specific provider (network/gps)
*/
private static Location getLocationByProvider(String provider, Context ctxt) {
Location location = null;
// if (!isProviderSupported(provider)) {
// return null;
// }
LocationManager locationManager = (LocationManager) ctxt
.getSystemService(Context.LOCATION_SERVICE);
try {
if (locationManager.isProviderEnabled(provider)) {
location = locationManager.getLastKnownLocation(provider);
}
} catch (IllegalArgumentException e) {
Log.i("New Location Receiver", "Cannot access Provider " + provider);
}
return location;
}
C'est la façon dont je demande des autorisations utilisateur.
En dehors de votre balise d'application dans AndroidManifest.xml, ajoutez ces demandes d'autorisation.
<uses-permission Android:name="Android.permission.INTERNET" />
<uses-permission Android:name="Android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission Android:name="Android.permission.ACCESS_FINE_LOCATION" />
Ajoutez ensuite les dépendances Google de la localisation dans le fichier App Gradle.
implementation 'com.google.Android.gms:play-services-location:15.0.0'
Déclarez maintenant quelques variables globales.
private lateinit var mFusedLocationProvider:FusedLocationProviderClient
private lateinit var mLocationCallback: LocationCallback
private lateinit var mLocationRequest: LocationRequest
private var mLocationPermissionGranted:Boolean = false
Dans la méthode OnCreate de votre activité (je n'ai pas pu formater le code correctement, excuses pour cela)
mFusedLocationProvider = LocationServices.getFusedLocationProviderClient(this)
//Location Callback
mLocationCallback = object: LocationCallback(){
override fun onLocationResult(p0: LocationResult?) {
if(p0==null){
//todo(request user to enable location from settings then remove return)
return
}else{
getDeviceLocation()
}
}
}
//Location Request
mLocationRequest = LocationRequest.create()
mLocationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
//Set the Interval for Latest Interval Update
mLocationRequest.interval = 5000
//Set How Many Location Updated you Want
mLocationRequest.numUpdates = 1
getLocationPermission()
getDeviceLocation()
Maintenant, créez les deux fonctions.
private fun getLocationPermission() {
val permission:Array<String> = arrayOf(Android.Manifest.permission.ACCESS_FINE_LOCATION,Android.Manifest.permission.ACCESS_COARSE_LOCATION)
if(ContextCompat.checkSelfPermission(applicationContext,Constant.FINE_LOCATION)== PermissionChecker.PERMISSION_GRANTED){
if(ContextCompat.checkSelfPermission(applicationContext,Constant.COARSE_LOCATION)== PermissionChecker.PERMISSION_GRANTED){
mLocationPermissionGranted = true
}
}else{
ActivityCompat.requestPermissions(this,permission,Constant.LOCATION_REQUEST_CODE)
}
}
Deuxième méthode
private fun getDeviceLocation() {
try{
if(mLocationPermissionGranted){
mFusedLocationProvider.lastLocation.addOnCompleteListener(this,{task: Task<Location> ->
if(task.isSuccessful){
var currentLocation: Location? = task.result
if(currentLocation!=null){
Log.i("Location","Latitude is ${currentLocation.latitude} and Longitude" +
"${currentLocation.longitude}")
}
else
mFusedLocationProvider.requestLocationUpdates(mLocationRequest,mLocationCallback,null)
}
})
}
}catch (e:SecurityException){
Log.e("Error", "Security Exception ${e.message}")
}
}
Pour Constant.kt
class Constant{
companion object {
//Location Request Settings
const val SET_INTERVAL:Long = 2000
const val NUM_UPDATES:Int = 1
//Location Permission
const val FINE_LOCATION:String = Android.Manifest.permission.ACCESS_FINE_LOCATION
const val COARSE_LOCATION:String = Android.Manifest.permission.ACCESS_COARSE_LOCATION
}
}
Récemment refactorisé pour obtenir l'emplacement du code, apprendre quelques bonnes idées et finalement obtenir une bibliothèque et une démo relativement parfaites.
//request all valid provider(network/gps)
private boolean requestAllProviderUpdates() {
checkRuntimeEnvironment();
checkPermission();
if (isRequesting) {
EasyLog.d("Request location update is busy");
return false;
}
long minTime = getCheckTimeInterval();
float minDistance = getCheckMinDistance();
if (mMapLocationListeners == null) {
mMapLocationListeners = new HashMap<>();
}
mValidProviders = getValidProviders();
if (mValidProviders == null || mValidProviders.isEmpty()) {
throw new IllegalArgumentException("Not available provider.");
}
for (String provider : mValidProviders) {
LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
if (location == null) {
EasyLog.e("LocationListener callback location is null.");
return;
}
printf(location);
mLastProviderTimestamp = location.getTime();
if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) {
finishResult(location);
} else {
doLocationResult(location);
}
removeProvider(location.getProvider());
if (isEmptyValidProviders()) {
requestTimeoutMsgInit();
removeUpdates();
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
};
getLocationManager().requestLocationUpdates(provider, minTime, minDistance, locationListener);
mMapLocationListeners.put(provider, locationListener);
EasyLog.d("Location request %s provider update.", provider);
}
isRequesting = true;
return true;
}
//remove request update
public void removeUpdates() {
checkRuntimeEnvironment();
LocationManager locationManager = getLocationManager();
if (mMapLocationListeners != null) {
Set<String> keys = mMapLocationListeners.keySet();
for (String key : keys) {
LocationListener locationListener = mMapLocationListeners.get(key);
if (locationListener != null) {
locationManager.removeUpdates(locationListener);
EasyLog.d("Remove location update, provider is " + key);
}
}
mMapLocationListeners.clear();
isRequesting = false;
}
}
//Compared with the last successful position, to determine whether you need to filter
private boolean isNeedFilter(Location location) {
checkLocation(location);
if (mLastLocation != null) {
float distance = location.distanceTo(mLastLocation);
if (distance < getCheckMinDistance()) {
return true;
}
if (location.getAccuracy() >= mLastLocation.getAccuracy()
&& distance < location.getAccuracy()) {
return true;
}
if (location.getTime() <= mLastProviderTimestamp) {
return true;
}
}
return false;
}
private void doLocationResult(Location location) {
checkLocation(location);
if (isNeedFilter(location)) {
EasyLog.d("location need to filtered out, timestamp is " + location.getTime());
finishResult(mLastLocation);
} else {
finishResult(location);
}
}
//Return to the finished position
private void finishResult(Location location) {
checkLocation(location);
double latitude = location.getLatitude();
double longitude = location.getLongitude();
float accuracy = location.getAccuracy();
long time = location.getTime();
String provider = location.getProvider();
if (mLocationResultListeners != null && !mLocationResultListeners.isEmpty()) {
String format = "Location result:<%f, %f> Accuracy:%f Time:%d Provider:%s";
EasyLog.i(String.format(format, latitude, longitude, accuracy, time, provider));
mLastLocation = location;
synchronized (this) {
Iterator<LocationResultListener> iterator = mLocationResultListeners.iterator();
while (iterator.hasNext()) {
LocationResultListener listener = iterator.next();
if (listener != null) {
listener.onResult(location);
}
iterator.remove();
}
}
}
}
Code complet: https://github.com/bingerz/FastLocation/blob/master/fastlocationlib/src/main/Java/cn/bingerz/fastlocation/FastLocation.Java
* Il est préférable d’enlever les mises à jour à chaque demande pour compléter la localisation, sinon la barre d’état du téléphone affichera toujours l’icône de positionnement.
En utilisant FusedLocationProviderApi qui est la dernière API et la meilleure parmi les possibilités disponibles pour obtenir un emplacement dans Android . Ajoutez ceci dans le fichier build.gradle
dependencies {
compile 'com.google.Android.gms:play-services:6.5.87'
}
vous pouvez obtenir le code source complet par cette adresse http://javapapers.com/Android/android-location-fused-provider/
Après avoir vu toutes les réponses, et question (Simple et Robuste). Je n'ai cliqué que sur la bibliothèque Android-ReactiveLocation .
Quand j'ai fait une application de suivi de localisation. Ensuite, j’ai réalisé que c’est très typique de gérer le suivi d’emplacement avec une batterie optimisée.
Je tiens donc à informer les développeurs et les développeurs qui ne souhaitent pas conserver leur code de localisation avec les optimisations futures. Utilisez cette bibliothèque.
ReactiveLocationProvider locationProvider = new
ReactiveLocationProvider(context);
locationProvider.getLastKnownLocation()
.subscribe(new Consumer<Location>() {
@Override
public void call(Location location) {
doSthImportantWithObtainedLocation(location);
}
});
Dépendances à mettre au niveau de l'application build.gradle
dependencies {
...
compile 'pl.charmas.Android:android-reactive-location2:2.1@aar'
compile 'com.google.Android.gms:play-services-location:11.0.4' //you can use newer GMS version if you need
compile 'com.google.Android.gms:play-services-places:11.0.4'
compile 'io.reactivex:rxjava:2.0.5' //you can override RxJava version if you need
}
Les pros pour utiliser cette librairie:
Voici ce que je fais:
mFinalLocation
).onDestroy()
, arrête d'écouter les mises à jour d'emplacement pour chacun des fournisseurs.Vous trouverez ci-dessous le code de service. Vous pouvez l'exécuter en fonction de la fréquence de mise à jour de l'emplacement dont vous avez besoin.
import Android.app.Service;
import Android.content.Context;
import Android.content.Intent;
import Android.location.Location;
import Android.location.LocationListener;
import Android.location.LocationManager;
import Android.os.Bundle;
import Android.os.Handler;
import Android.os.IBinder;
import Android.os.Message;
import Android.support.annotation.Nullable;
import Android.util.Log;
public class RecordLocationService extends Service {
private final String TAG = RecordLocationService.class.getSimpleName();
private final int TWO_MINUTES = 1000 * 60 * 2;
private LocationManager mLocationManager;
private MyLocationListener mLocationListeners[] = new MyLocationListener[]{
new MyLocationListener(LocationManager.NETWORK_PROVIDER),
new MyLocationListener(LocationManager.GPS_PROVIDER)
};
private Location mFinalLocation;
private class MyLocationListener implements LocationListener {
private String mProvider;
public MyLocationListener(String provider) {
Log.d(TAG, "LocationListener : " + provider);
mProvider = provider;
}
public String getProvider() {
return mProvider;
}
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, "onLocationChanged : " + location);
if (isBetterLocation(location, mFinalLocation)) {
Log.d(TAG, "Setting current Final Location to recent most Location for Provider : " + location.getProvider());
Log.d(TAG, "Setting current Final Location to : " + location);
mFinalLocation = location;
} else {
Log.d(TAG, "Keeping current Final Location to previous Final Location");
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TAG, "onStatusChanged provider " + provider);
}
@Override
public void onProviderEnabled(String provider) {
Log.d(TAG, "onProviderEnabled provider " + provider);
}
@Override
public void onProviderDisabled(String provider) {
Log.d(TAG, "onProviderDisabled provider " + provider);
}
}
private Handler mStopServiceHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1: {
stopSelf();
}
break;
}
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.d(TAG, "onStartCommand");
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
requestLocation();
mStopServiceHandler.sendEmptyMessageDelayed(1, TWO_MINUTES);
}
private void requestLocation() {
// Acquire a reference to the system Location Manager
if (mLocationManager == null) {
mLocationManager = (LocationManager) this.getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
try {
if (mLocationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER) && mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Log.d(TAG, "Fetching Cached Location for Provider : " + LocationManager.NETWORK_PROVIDER);
Location cachedNetworkLocation = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (cachedNetworkLocation != null) {
Log.d(TAG, "Setting Final Location to Cached Location for Provider : " + LocationManager.NETWORK_PROVIDER);
Log.d(TAG, "Setting Final Location to : " + cachedNetworkLocation);
mFinalLocation = cachedNetworkLocation;
} else {
Log.d(TAG, "Cached Location for Provider : " + LocationManager.NETWORK_PROVIDER + " is NULL");
}
Log.d(TAG, "Requesting Location Update for Provider : " + LocationManager.NETWORK_PROVIDER);
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mLocationListeners[0]);
}
} catch (SecurityException se) {
Log.e(TAG, se.getMessage(), se);
} catch (IllegalArgumentException iae) {
Log.e(TAG, iae.getMessage(), iae);
}
try {
if (mLocationManager.getAllProviders().contains(LocationManager.GPS_PROVIDER) && mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.d(TAG, "Fetching Cached Location for Provider : " + LocationManager.GPS_PROVIDER);
Location cachedGPSLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (cachedGPSLocation != null) {
if (isBetterLocation(cachedGPSLocation, mFinalLocation)) {
Log.d(TAG, "Setting Final Location to Cached Location for Provider : " + LocationManager.GPS_PROVIDER);
Log.d(TAG, "Setting Final Location to : " + cachedGPSLocation);
mFinalLocation = cachedGPSLocation;
}
} else {
Log.d(TAG, "Cached Location for Provider : " + LocationManager.GPS_PROVIDER + " is NULL");
}
Log.d(TAG, "Requesting Location Update for Provider : " + LocationManager.GPS_PROVIDER);
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListeners[1]);
}
} catch (SecurityException se) {
Log.e(TAG, se.getMessage(), se);
} catch (IllegalArgumentException iae) {
Log.e(TAG, iae.getMessage(), iae);
}
}
/**
* Determines whether one Location reading is better than the current Location fix
*
* @param location The new Location that you want to evaluate
* @param currentBestLocation The current Location fix, to which you want to compare the new one
*/
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
/**
* Checks whether two providers are the same
*/
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
try {
Log.d(TAG, "Removing Location Update for Provider : " + mLocationListeners[i].getProvider());
mLocationManager.removeUpdates(mLocationListeners[i]);
} catch (Exception ex) {
Log.e(TAG, "fail to remove location listeners, ignore", ex);
}
}
}
}
}
Version Kotlin de @Fedor Greate answer:
utilisation de la classe:
val locationResult = object : MyLocation.LocationResult() {
override fun gotLocation(location: Location?) {
val lat = location!!.latitude
val lon = location.longitude
Toast.makeText(context, "$lat --SLocRes-- $lon", Toast.LENGTH_SHORT).show()
}
}
val myLocation = MyLocation()
myLocation.getLocation(inflater.context, locationResult)
MyLocation
Classe:
class MyLocation {
internal lateinit var timer1: Timer
internal var lm: LocationManager? = null
internal lateinit var locationResult: LocationResult
internal var gps_enabled = false
internal var network_enabled = false
internal var locationListenerGps: LocationListener = object : LocationListener {
override fun onLocationChanged(location: Location) {
timer1.cancel()
locationResult.gotLocation(location)
lm!!.removeUpdates(this)
lm!!.removeUpdates(locationListenerNetwork)
}
override fun onProviderDisabled(provider: String) {}
override fun onProviderEnabled(provider: String) {}
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}
}
internal var locationListenerNetwork: LocationListener = object : LocationListener {
override fun onLocationChanged(location: Location) {
timer1.cancel()
locationResult.gotLocation(location)
lm!!.removeUpdates(this)
lm!!.removeUpdates(locationListenerGps)
}
override fun onProviderDisabled(provider: String) {}
override fun onProviderEnabled(provider: String) {}
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}
}
fun getLocation(context: Context, result: LocationResult): Boolean {
//I use LocationResult callback class to pass location value from MyLocation to user code.
locationResult = result
if (lm == null)
lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager?
//exceptions will be thrown if provider is not permitted.
try {
gps_enabled = lm!!.isProviderEnabled(LocationManager.GPS_PROVIDER)
} catch (ex: Exception) {
}
try {
network_enabled = lm!!.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
} catch (ex: Exception) {
}
//don't start listeners if no provider is enabled
if (!gps_enabled && !network_enabled)
return false
if (ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) run {
ActivityCompat.requestPermissions(context as Activity,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), 111)
}
if (gps_enabled)
lm!!.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0f, locationListenerGps)
if (network_enabled)
lm!!.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0f, locationListenerNetwork)
timer1 = Timer()
timer1.schedule(GetLastLocation(context), 20000)
return true
}
internal inner class GetLastLocation(var context: Context) : TimerTask() {
override fun run() {
lm!!.removeUpdates(locationListenerGps)
lm!!.removeUpdates(locationListenerNetwork)
var net_loc: Location? = null
var gps_loc: Location? = null
if (ActivityCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ||
ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
) run {
ActivityCompat.requestPermissions(context as Activity,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION),111)
}
if (gps_enabled)
gps_loc = lm!!.getLastKnownLocation(LocationManager.GPS_PROVIDER)
if (network_enabled)
net_loc = lm!!.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
//if there are both values use the latest one
if (gps_loc != null && net_loc != null) {
if (gps_loc.getTime() > net_loc.getTime())
locationResult.gotLocation(gps_loc)
else
locationResult.gotLocation(net_loc)
return
}
if (gps_loc != null) {
locationResult.gotLocation(gps_loc)
return
}
if (net_loc != null) {
locationResult.gotLocation(net_loc)
return
}
locationResult.gotLocation(null)
}
}
abstract class LocationResult {
abstract fun gotLocation(location: Location?)
}
}