Доступ LocationManager / LocationListener из класса - PullRequest
3 голосов
/ 13 октября 2011

Я немного растерялся: в своей основной деятельности я регистрирую LocationManager и подключаю его к LocationListener, чтобы использовать myLocation.getLatitude () и тому подобное.

Теперь мне нужно использовать Location-методы из другого класса.

Я не могу использовать эти объекты из другого класса, потому что не могу определить основной вид деятельности. Я не могу использовать геттеры для передачи L.Manager или L.Listener, потому что они снова нестатичны.

Итак, в общем, как мне получить доступ к объектам, которые я создал в основной деятельности? Любые советы о том, как организовать это лучше? Является ли класс LocationListener внутри основного класса активности глупой вещью в целом?

public class URNavActivity extends Activity

{
    public LocationManager mlocManager;
    public LocationListener mlocListener;
...
}

public void onCreate(Bundle savedInstanceState)
{       
    super.onCreate(savedInstanceState);
    mResourceProxy = new DefaultResourceProxyImpl(getApplicationContext());

    actVar=this;

    initGraph();
    setMap();
    gpsEnable();
    initMyLocation();
    getItems();
    initOverlay();
}

public void gpsEnable ()
{
    mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

    mlocListener = new MyLocationListener();

    mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
}

public class MyLocationListener implements LocationListener

{

@Override

public void onLocationChanged(Location loc)

{

    loc.getLatitude();
    loc.getLongitude();
    myMap.getController().setCenter(new GeoPoint(lati, longi));
}

Ответы [ 3 ]

9 голосов
/ 24 октября 2011

Прежде всего, ваш LocationListener не должен быть частью деятельности.Действия имеют четко определенный жизненный цикл и могут создаваться и разрушаться платформой Android по мере необходимости.Поэтому переменные экземпляра вашей Деятельности необходимо будет повторно инициализировать в методе onResume () вашей активности, что сделает их совершенно непригодными для длительного хранения.

Итак.Начните с создания липкой службы для управления запуском и остановкой обновлений местоположения.Прилипание означает, что экземпляр службы зависает между вызовами, и поэтому вы можете надежно использовать переменные экземпляра и знать, что они будут сохранять свои значения до тех пор, пока служба не будет прервана.Эта служба также должна реализовывать интерфейс LocationListener, и теперь она может хранить местоположение, уведомленное об этом при вызове onLocationChanged:

public class LocationService extends Service implements LocationListener {

    private LocationManager locationManager;

    private Location location;

    @Override
    public int onStartCommand(final Intent intent, final int flags, final int startId) {

        Logging.i(CLAZZ, "onHandleIntent", "invoked");

        if (intent.getAction().equals("startListening")) {
            locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
        }
        else {
            if (intent.getAction().equals("stopListening")) {
                locationManager.removeUpdates(this);
                locationManager = null;
            }
        }

        return START_STICKY;

    }

    @Override
    public IBinder onBind(final Intent intent) {
        return null;
    }

    public void onLocationChanged(final Location location) {
        this.location = location;   
        // TODO this is where you'd do something like context.sendBroadcast()
    }

    public void onProviderDisabled(final String provider) {
    }

    public void onProviderEnabled(final String provider) {
    }

    public void onStatusChanged(final String arg0, final int arg1, final Bundle arg2) {
    }

}

Теперь у вас есть служба, которую вы можете запускать и останавливать обновления местоположения по мере необходимости.,Это также позволяет вам продолжать получать и обрабатывать изменения местоположения, даже если ваше приложение находится не на переднем плане, если это именно то, что вам нужно.

Теперь у вас есть два способа сделать эту информацию о местоположении доступной: Использоватьcontext.sendBroadcast () для распространения нового Location для (например) действия или использования подхода связанной службы, чтобы позволить другим классам вызывать открытый API и получать Location.См. http://developer.android.com/guide/topics/fundamentals/bound-services.html для получения дополнительной информации о создании связанной службы.

Обратите внимание, что существует множество других аспектов прослушивания обновлений местоположения, которые я здесь не включил, для ясности.

1 голос
/ 14 октября 2011

Я бы предложил два элегантных способа получить доступ к вашему объекту из любого места:

  1. используйте Singleton шаблон проектирования
  2. использовать класс ProjectApp. К этому классу можно получить доступ из любого действия, просто вызвав getApplication ().

    ProjectApp app = (ProjectApp) getApplication ();

Я использовал комбинацию из двух:

    public class MyApp extends Application {

    private MyLocation mMyLocation;

    @Override
    public void onCreate() {
        super.onCreate();
        mMyLocation = new MyLocation();
        mMyLocation.getLocation(this, GlobalData.getInstance(), true);
    }
}

Вы можете видеть, что GlobalData является одноэлементным классом, который реализует интерфейс LocationResult, что означает, что он будет отправлять обновленное местоположение этому объекту. Когда мне нужно получить обновленное местоположение, я беру его из GlobalData.

Вот реализация класса MyLocation (здесь я использовал код из и внес некоторые изменения:

package com.pinhassi.android.utilslib;


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 {
    private Timer timer1;
    private LocationManager lm;
    private LocationResult locationResult;
    private boolean gps_enabled=false;
    private boolean network_enabled=false;

    private boolean mContinuesUpdates;
    private int decimalAccuracy; 

    /**
     * Class constructor
     */
    public MyLocation(){
        decimalAccuracy = 0;
    }

    public boolean getLocation(Context context, LocationResult result, boolean continuesUpdates)
    {
        mContinuesUpdates = continuesUpdates;
        //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(getDecimalAccurated(location));
            if (!mContinuesUpdates)
                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(getDecimalAccurated(location));
            if (!mContinuesUpdates)
                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(getDecimalAccurated(gps_loc));
                 else
                     locationResult.gotLocation(getDecimalAccurated(net_loc));
                 return;
             }

             if(gps_loc!=null){
                 locationResult.gotLocation(getDecimalAccurated(gps_loc));
                 return;
             }
             if(net_loc!=null){
                 locationResult.gotLocation(getDecimalAccurated(net_loc));
                     return;
                 }
                 locationResult.gotLocation(null);
            }
        }

        /**
         * called when the GPS returns a location.
         * can be called multiple times as the location is updated
         */
        public interface LocationResult {
            public void gotLocation(Location location);
        }

        /**
         * sets location result accuracy
         * @param n number of places after the point. negative value or 0 means not set.
         */
        public void setDecimalAccuracy(int n)
        {
            this.decimalAccuracy = n;
        }

        private Location getDecimalAccurated(Location location) {
            if (decimalAccuracy > 0){
            double accuracy = Math.pow(10, this.decimalAccuracy);
            int ix;

            ix = (int)(location.getLatitude() * accuracy); 
            location.setLatitude(((double)ix)/accuracy);

            ix = (int)(location.getLongitude() * accuracy); 
            location.setLongitude(((double)ix)/accuracy);
            }

            return location;
        }

    }
0 голосов
/ 14 октября 2011

Я поговорю в общем, поскольку у меня была такая же проблема Как управлять LocationListener и освещать этот слушатель доступ к деятельности ..

Это была моя попытка:

Слушатель:

public class MyLocationListener  implements LocationListener{
    ProgressDialog dialog;
    LocationManager locManager;
    Context context;

    public MyLocationListener  (Context context,ProgressDialog dialog){

        this.context = context;
        this.dialog = dialog;
    }  

    public void startSearch() {

        locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

        // If the network provider works run it , else try GPS  provider
        // TODO : what happens if GPS and Network providers are not suuported ??


            if(!locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) )
                locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
                        0, this);
            else
                locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0,
                        0, this);

                dialog = new ProgressDialog(context);
                dialog.setTitle("");
                dialog.setMessage(context.getString(R.string.pleaseWait));
                dialog.setButton(context.getString(R.string.cancel), new DialogInterface.OnClickListener() 
                {
                    public void onClick(DialogInterface dialog, int which) 
                    {
                        locManager.removeUpdates(MyLocationListener .this);
                        dialog.dismiss();
                        return;
                    }
                });

            dialog.show();

    } 

    // Location Listener implementation
    // read Android doc for more info
    // this methods is triggered when new location ( latitiude and longitude ) is found by the system
    private void updateWithNewLocation(Location location) {


        if (location != null) {
            double lat = location.getLatitude();
            double lng = location.getLongitude();

            //THIS IS MY ACTIVITY
            MainActivity mainActivity = (MainActivity) context;
            mainActivity.init();

        } else {
            //this.setSummary( "No location found" );
        }
        // remove the listener , we don't need it anymore
        locManager.removeUpdates(this);
        dialog.hide();
    }

    public void onLocationChanged(Location location) {
        updateWithNewLocation(location);
    }

    public void onProviderDisabled(String provider) {
        updateWithNewLocation(null);
    }

    public void onProviderEnabled(String provider) {
    }

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



}

инициализировать слушателя в MainActivity так:

ProgressDialog dialog;
.
.
.
new MyLocationListener  (this, dialog).startSearch();

Не знаю, поможет ли это? но это было мое решение ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...