2011-10-13 18 views
3
的位置管理器/位置偵聽器

我有點不知所措:在我的主要活動中,我註冊了一個LocationManager並將其連接到一個LocationListener以使用myLocation.getLatitude()等。訪問類

現在我需要使用另一個類的位置方法。

我不能使用這些對象從另一個類,因爲我不能intantianti主要活動。 我不能使用getters傳遞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)); 
} 

回答

9

首先您LocationListener的不應該是一個活動的一部分,活動有明確的生命週期,可以來由Android框架根據需要生成並銷燬,因此您的Activity的實例變量需要在您的activity的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()將新位置傳播到(例如)一個活動,或使用綁定的服務方法允許其他類調用暴露的API並獲取位置。有關創建綁定服務的更多詳細信息,請參見http://developer.android.com/guide/topics/fundamentals/bound-services.html

請注意,爲了清楚起見,還有許多其他方面的信息來監聽位置更新,我沒有將其包含在此處。

+4

我會非常感興趣的聽到其他方面的... –

+0

首先很多其他的答案這裏在stackoverflow,什麼工程!我錯過了'在我的代碼中實現LocationListener'。我在服務中創建了一個監聽器,並且遇到了阻止這個問題的問題。 PS:你可以使用'onDestroy(){locationManager.removeUpdates(this); \t locationManager = null; \t stopSelf(); \t super.onDestroy(); }'停止經理。 – Eugen

+0

非常感謝!但是如何在這裏檢查運行時權限? –

0

,因爲我有同樣的問題,我會在一般的談話: 如何管理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(); 

我不知道是否有幫助?但是這是我的解決方案...

+0

我已經更新了答案.. – Abdullah

1

我會提供了兩個優雅的方式從任何地方訪問你的對象:

  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); 
    } 
} 

你可以看到,全球國際是實現LocationResult接口,這意味着它會發送更新的位置此對象的一個​​單例類。 當我需要獲取更新位置時,我從GlobalData中獲取它。

這裏是MyLocation類實現(我用了一些代碼here並做了一些改動:

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; 
     } 

    }