web-dev-qa-db-fra.com

Android - Meilleur moyen d'implémenter LocationListener sur plusieurs activités

Je suis coincé sur ce problème depuis un certain temps. Je travaille sur une application qui utilise très largement la localisation dans plusieurs activités différentes. Chaque exemple que j'ai trouvé utilise un emplacementListener distinct dans chaque activité. Ce n'est pas faisable dans ma situation.

Je me demande quel est le moyen le plus efficace de garder une trace de l'emplacement de l'utilisateur sur plusieurs activités. À l'heure actuelle, j'ai créé un service qui implémente LocationListener et utilise une diffusion pour mettre à jour les champs lat et stat statiques dans une classe de base d'activité. Cela signifie que le service fonctionne toujours, ce qui n'est pas idéal. Mais si j'arrête le service et le redémarre uniquement lorsque j'en ai besoin, il faut du temps pour obtenir un bon emplacement. J'ai besoin des données de localisation dans onCreate () de l'activité. C'est la même chose si j'essaye de l'implémenter dans la classe de base d'activité. Si j'enregistre constamment l'auditeur dans onResume/onCreate et le désinscris dans onPause (), cela prend trop de temps pour commencer à recevoir des mises à jour. J'ai également essayé de créer un service auquel je pouvais me lier, il ne démarre donc que lorsque j'ai besoin d'un emplacement. Mais j'ai le même problème, il faut trop de temps pour se lier au service et commencer à obtenir des mises à jour.

Le service que j'utilise maintenant fonctionne, mais d'après tout ce que j'ai lu, je ne devrais pas utiliser un service en cours d'exécution pour des choses triviales comme celle-ci. Mais le but de l'application est de fournir des données pertinentes en fonction de l'emplacement actuel de l'utilisateur. J'ai donc un service qui s'exécute en arrière-plan et fournit des mises à jour périodiquement. Le seul problème majeur qui m'a amené à réexaminer la conception à ce stade est que j'ai récemment découvert que onProviderEnabled () n'est pas appelé si l'utilisateur démarre l'application sans que le GPS soit allumé, puis l'active ensuite. Dans ce scénario, l'application n'a aucun moyen de reconnaître que le GPS a été activé afin qu'elle puisse commencer à écouter les mises à jour.

Je pensais avoir compris LocationManager et LocationListener en regardant les exemples, mais je n'arrive pas à les appliquer à cette situation où j'ai besoin de données de localisation dans plusieurs activités. Toute aide ou conseil serait grandement apprécié.

40
d370urn3ur

La manière dont j'implémenterais généralement cette exigence utilise une implémentation de service liée, comme celle de Local Service Sample dans la documentation du SDK. De toute évidence, vous connaissez l'avantage du service qui vous permet de créer tout le code de localisation une seule fois.

L'accès au service via des liaisons permet au service de démarrer et de s'arrêter de sorte qu'il ne s'exécute pas lorsque votre application n'est pas au premier plan (elle s'éteindra dès que plus aucune activité ne sera liée). La clé, IMO, pour que cela fonctionne bien est de lier le service dans onStart() et de LIER dans onStop(), car ces deux appels se chevauchent lorsque vous passez d'une activité à une autre (deuxième activité Commence avant que le premier ne s'arrête). Cela empêche le service de mourir lorsqu'il se déplace à l'intérieur de l'application et ne laisse le service mourir que lorsque l'application entière (ou au moins toute partie intéressée par l'emplacement) quitte le premier plan.

Avec les liaisons, vous n'avez pas à transmettre les données de localisation dans une diffusion, car l'activité peut appeler des méthodes directement sur le service pour obtenir la dernière localisation. Cependant, une diffusion serait toujours avantageuse comme méthode pour indiquer QUAND une nouvelle mise à jour est disponible ... mais cela deviendrait simplement un notifiant à l'activité d'écoute pour appeler la méthode getLocation() sur le service.

Mon 0,02 $. J'espère que cela pourra aider!

43
Devunwired

J'ai eu le même problème et j'ai essayé de le résoudre avec la bonne réponse de Devunwired, mais j'ai eu quelques problèmes. Je n'ai pas trouvé de moyen d'arrêter le service et lorsque j'ai terminé mon application, le module GPS était toujours en cours d'exécution. J'ai donc trouvé un autre moyen:

J'ai écrit un cours GPS.Java:

public class GPS {

    private IGPSActivity main;

    // Helper for GPS-Position
    private LocationListener mlocListener;
    private LocationManager mlocManager;

    private boolean isRunning;

    public GPS(IGPSActivity main) {
        this.main = main;

        // GPS Position
        mlocManager = (LocationManager) ((Activity) this.main).getSystemService(Context.LOCATION_SERVICE);
        mlocListener = new MyLocationListener();
        mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
        // GPS Position END
        this.isRunning = true;
    }

    public void stopGPS() {
        if(isRunning) {
            mlocManager.removeUpdates(mlocListener);
            this.isRunning = false;
        }
    }

    public void resumeGPS() {
        mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
        this.isRunning = true;
    }

    public boolean isRunning() {
        return this.isRunning;
    }

    public class MyLocationListener implements LocationListener {

        private final String TAG = MyLocationListener.class.getSimpleName();

        @Override
        public void onLocationChanged(Location loc) {
            GPS.this.main.locationChanged(loc.getLongitude(), loc.getLatitude());
        }

        @Override
        public void onProviderDisabled(String provider) {
            GPS.this.main.displayGPSSettingsDialog();
        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

    }

}

Cette classe est utilisée dans chaque activité qui a besoin des coordonnées GPS. Chaque activité doit implémenter l'interface suivante (nécessaire pour la communication):

public interface IGPSActivity {
    public void locationChanged(double longitude, double latitude);
    public void displayGPSSettingsDialog();
}

Maintenant, mon activité principale ressemble à ça:

public class MainActivity extends Activity implements IGPSActivity {

    private GPS gps;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        gps = new GPS(this);
    }


    @Override
    protected void onResume() { 
        if(!gps.isRunning()) gps.resumeGPS();   
        super.onResume();
    }

    @Override
    protected void onStop() {
        gps.stopGPS();
        super.onStop();
    }


    public void locationChanged(double longitude, double latitude) {
        Log.d(TAG, "Main-Longitude: " + longitude);
        Log.d(TAG, "Main-Latitude: " + latitude);
    }


    @Override
    public void displayGPSSettingsDialog() {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(intent);
    }
}

et un deuxième comme ça:

public class TEST4GPS extends Activity implements IGPSActivity{

    private GPS gps;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.gps = new GPS(this);
    }

    @Override
    public void locationChanged(double longitude, double latitude) {
        Log.d("TEST", "Test-Longitude: " + longitude);
        Log.d("TEST", "Test-Latitude: " + latitude);

    }

    @Override
    protected void onResume() { 
        if(!gps.isRunning()) gps.resumeGPS();   
        super. onResume();
    }

    @Override
    protected void onStop() {
        gps.stopGPS();
        super.onStop();
    }

    @Override
    public void displayGPSSettingsDialog() {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                startActivity(intent);

    }
}

Ce n'est pas aussi beau que la solution de Devunwired, mais ça marche pour moi. cya

17
Spipau

Vous pouvez demander à votre service d'écrire vos accords lat et long sur une base de données sqlite lors d'un changement de cette façon, vous n'avez pas de frais généraux de liaison de service et vos accords seront accessibles dans toutes vos activités.

Peut-être que dans votre activité principale, vous pouvez vérifier l'état du GPS et s'il est désactivé, vous pouvez inviter l'utilisateur à l'activer. Une fois le GPS activé, démarrez votre service.

0
travega