2015-04-04 54 views
16

我想在我的Android項目,並以做簡單的檢索設備的位置,所以我使用的播放服務的方法:FusedLocationApi.getLastLocation總是空

  protected synchronized void buildGoogleApiClient() { 

    mGoogleApiClient = new GoogleApiClient.Builder(MainSearchActivity.this) 
     .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() { 
      @Override 
      public void onConnected(Bundle bundle){ 
       Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
       if(location == null){ 
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, new LocationListener() { 
         @Override 
         public void onLocationChanged(Location location) { 
          lastLocation = location; 
         } 
        }); 
       } 
      } 
      @Override 
      public void onConnectionSuspended(int i){ 

      } 

     }) 
     .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() { 
      @Override 
      public void onConnectionFailed(ConnectionResult connectionResult){ 
       if(connectionResult.hasResolution()){ 
        try { 
         // Start an Activity that tries to resolve the error 
         connectionResult.startResolutionForResult(MainSearchActivity.this, CONNECTION_FAILURE_RESOLUTION_REQUEST); 
        }catch(IntentSender.SendIntentException e){ 
         e.printStackTrace(); 
        } 
       }else{ 
        Utils.logger("Location services connection failed with code " + connectionResult.getErrorCode(), Utils.LOG_DEBUG); 
       } 
      } 
     }) 
     .addApi(LocationServices.API) 
     .build(); 

    mGoogleApiClient.connect(); 
} 

public Location retrieveLastLocation(){ 
    Location loc = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
    if(loc == null) 
    { 

    } 
    return loc; //TODO: What if loc is null? 
} 

但LOC變量總是空。在不同的手機上,每次都是如此。此外,我試圖在onLocationChanged中分配的lastLocation永遠不會更改。始終爲空。

這些是我的應用程序

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
<uses-permission android:name="com.vogella.android.locationapi.maps.permission.MAPS_RECEIVE" /> 
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" /> 

我只是不明白它設置權限:爲什麼不能LocationServices檢索位置?我有三個啓用的所有地理位置設置deviced我在測試: -/

感謝您的幫助

+0

我請你,請看一看這個答案http://stackoverflow.com/a/35833552/3278589 – Subho 2017-02-17 13:52:00

回答

20

的融合,如果至少一個客戶端連接到它Location Provider只會保持背景的位置。現在只要打開位置服務就不能保證存儲上次已知的位置。

一旦第一個客戶端連接,它會立即設法得到一個位置。如果您的活動是第一個連接的客戶端,並且onConnected()立即被調用,那麼第一個位置可能沒有足夠的時間到達。

我建議您先啓動地圖應用程序,至少有一些確認位置,然後測試你的應用程序。

+19

所以你說的是,當用戶在我們的應用程序,我們需要他們的位置,我們需要打開Goog​​le地圖應用程序,然後希望用戶能夠回到我們的應用程序? – 2015-05-15 19:27:13

+0

我並不是說你需要打開Goog​​le地圖。我所說的是,當你打電話給融合提供者時,需要有一些可用的位置數據。畢竟這是使用Fusion Provider的主要好處,不是嗎? – 2015-05-15 19:35:50

+9

所以如何強制一些位置獲取事件發生在我自己的應用程序中 – 2015-05-15 21:37:03

10

我覺得有一個小小的遺漏,這在我所顯示的代碼中是不可見的。

mGoogleApiClient已建成,但似乎沒有連接。您可以通過致電mGoogleApiClient.isConnected()進行驗證。

您可以重寫onStart方法並在那裏調用connect。或者,您可以覆蓋onResume(),以防您想要在您的活動可見時訪問該位置。

@Override 
protected void onStart() { 
    super.onStart(); 
    if (mGoogleApiClient != null) { 
     mGoogleApiClient.connect(); 
    } 
} 
+1

哇這對我工作,但使用它onConnected():)謝謝先生 – commonSenseCode 2015-07-18 11:58:51

2

如果getLastLocation()始終返回null,請嘗試使用此hack。我用它來解決我的問題。在您的活動中實施LocationListener(導入com.google.android.gms.location.LocationListener)。

protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_splash); 

     Context mContext = this; 

     manager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); 

     createLocationRequest(); 

     mGoogleApiClient = new GoogleApiClient.Builder(mContext) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API) 
       .build(); 
     mGoogleApiClient.connect(); 

} 

private void createLocationRequest(){ 
    mLocationRequest = LocationRequest.create(); 
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 
    mLocationRequest.setInterval(SET_INTERVAL); 
    mLocationRequest.setFastestInterval(FASTEST_INTERVAL); 
} 

在onStart或的onResume(I優選的onResume)

@Override 
protected void onResume() { 
    super.onResume(); 
    if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { 
     if (mGoogleApiClient != null) { 
      mGoogleApiClient.connect(); 
     } 
    }else{ 
     // Showyourmesg(); 
    } 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    if (mGoogleApiClient != null) { 
     mGoogleApiClient.disconnect(); 
    } 
} 

protected void startLocationUpdates(){ 
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, 
      mLocationRequest,this); 
} 

protected void stopLocationUpdates() { 
    LocationServices.FusedLocationApi.removeLocationUpdates(
      mGoogleApiClient, this); 
} 

現在,在onLocationChanged方法檢查googleApiClient是否連接與否。如果其連接,斷開連接並再次連接。

@Override 
public void onLocationChanged(Location location) { 
    Log.d("SplashAct", "LocatinChngListner, loc: " + location.getLatitude() + "," + location.getLongitude()); 

    if (mGoogleApiClient != null) 
     if (mGoogleApiClient.isConnected() || mGoogleApiClient.isConnecting()){ 
      mGoogleApiClient.disconnect(); 
      mGoogleApiClient.connect(); 
     } else if (!mGoogleApiClient.isConnected()){ 
      mGoogleApiClient.connect(); 
     } 
} 

最後,在你的onConntected()方法

@Override 
    public void onConnected(Bundle bundle) { 

    Log.d("ACTIVITY", "ApiClient: OnConnected"); 

    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
      mGoogleApiClient); 

    if (mLastLocation == null){ 
     startLocationUpdates(); // bind interface if your are not getting the lastlocation. or bind as per your requirement. 
    } 

    if (mLastLocation != null){ 
     while (latitude == 0 || longitude == 0){ 
      pDialog.setMessage("Getting Location"); 
      pDialog.show(); 

      latitude = mLastLocation.getLatitude(); 
      longitude = mLastLocation.getLongitude(); 

      if (latitude != 0 && longitude != 0){ 
       stopLocationUpdates(); // unbind the locationlistner here or wherever you want as per your requirement. 
       pDialog.dismiss(); // location data received, dismiss dialog, call your method or perform your task. 
      } 
     } 
    } 
} 

我們反覆嘗試連接到googleApiClient,即使它已經連接,這樣我們就可以得到lastLocation數據。這將取決於LocationRequest時間間隔。您也可以在onLocationChanged中獲取位置數據,然後從那裏執行您的任務。

+0

你的while循環有沒有結果在無盡的循環中,還是你總是得到一個位置?如果手機沒有連接性會發生什麼?如果沒有連接的GoogleApiClient,如何調用onLocationChanged()?好像你想從onLocationChanged事件中調用getLastLocation()而不是onConnected事件。 – 2016-11-09 14:43:53

+0

@JohnWard是的,我總是得到的位置和我的while循環永遠不會進入無盡模式,雖然是的有時甚至在獲得位置後,我無法執行進一步的任務,因爲我在兩個場合執行任務onLastLocation == null和lastLocation!= null。現在我已經將它改爲if-else條件,並且它工作得很好。連接?連接到互聯網或gps?連接到GPS是完全必需的。我想你不能在沒有連接GoogleApiClient的情況下調用onCochange。如果它使得OnConctd中的loc好,那麼從OnLocChngd中獲取。 – beginner 2016-12-29 07:15:05

0

這與Amit K.有關薩哈的回答,但對我來說,我的Lollipop設備之一,我不斷得到null。所以我打開了地圖應用程序,我在下面的屏幕上要求我打開所有的爵士樂來改善我的位置。

一旦我這樣做了一次,我的設備就能夠通過一次撥打getLastLocation()來接收位置;

我認爲那麼用戶可能還沒有使用他們的地圖應用程序,就必須要求這些應用程序安裝權限。

enter image description here

8

首先,創建一個LocationRequest對象:

// Create the LocationRequest object 
mLocationRequest = LocationRequest.create() 
    .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) 
    .setInterval(10 * 1000)  // 10 seconds, in milliseconds 
    .setFastestInterval(1 * 1000); // 1 second, in milliseconds 

然後,確保用戶已授予使用位置的權限。如果是這樣,從requestLocationUpdates獲得位置如下:

void getLocation() { 
    Location location = null; 
    if (ContextCompat.checkSelfPermission(activity, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
     ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1); 

     /*TODO!! INSERT CODE TO PROMPT USER TO GIVE PERMISSION*/ 

    } else { 
     LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); 
    } 

    mLastLocation = location; 
    LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this); 
} 

一定要刪除的更新,如果你只需要在沒有持續監控一個地點。這樣,你永遠不會得到一個空的Location

欲瞭解更多信息,請參閱http://blog.teamtreehouse.com/beginners-guide-location-android

+1

這是最好的答案,謝謝隊友! – 2016-11-12 07:37:45