FusedLocationApi.getLastLocation always null

匿名 (未验证) 提交于 2019-12-03 02:56:01

问题:

I'd like to simply retrieve device location in my Android project and in order to do so I use the play-services approach:

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

but the loc variable is ALWAYS null. It's as such on different phones, every single time. Also lastLocation, that I try to assign in the onLocationChanged, never changes. Always null.

These are the permission I set for the app

    

I just don't get it: why can't the LocationServices retrieve a position? I have all geolocation settings enabled on all three the deviced i tested upon :-/

Thank you for any help

回答1:

The fused Location Provider will only maintain background location if at least one client is connected to it. Now just turning on the location service will not guarantee to store the last known location.

Once the first client connects, it will immediately try to get a location. If your activity is the first client to connect and getLastLocation() is invoked right away in onConnected(), that might not be enough time for the first location to arrive..

I suggest you to launch the Maps app first, so that there is at least some confirmed location, and then test your app.



回答2:

I think there is a small miss which is not visible to me in the code shown.

The mGoogleApiClient is built but seems not connected.You can verify this by calling mGoogleApiClient.isConnected().

You can just override the onStart method and call connect there. Or you can override onResume() in case you want to access the location whenever ur activity is visible.

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


回答3:

First, create a LocationRequest object:

 // 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 

Then, make sure the user has granted permission to use location. If so, get the location from requestLocationUpdates as follows:

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

Be sure to remove the updates if you only need one location without constant monitoring. This way, you will never get a null Location.

For more information, go to http://blog.teamtreehouse.com/beginners-guide-location-android.



回答4:

If getLastLocation() is always returning null, try this hack. I have used it to solve my problem. Implement LocationListener (import com.google.android.gms.location.LocationListener) in your activity.

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 or onResume (i preferred 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); } 

Now, in your onLocationChanged method check whether the googleApiClient is connected or not. If its connected, disconnect it, and connect again.

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

And finally, in your onConntected() method

@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.             }         }     } } 

We are repeatedly trying to connect to googleApiClient, even if its already connected, so that we can get the lastLocation data. This will depend on the LocationRequest intervals. You can get the location data in onLocationChanged too, and perform your task from there.



回答5:

If you are using Android Marshmallow (API 23) or newer version of Android, you can face same problem because permission is not granted. You should either explicitly request permission at run time for location or, if it's a test project you can grant location permission from app settings on your phone.



回答6:

Here is the exact answer and explanation.

LocationClient getLastLocation() return null



回答7:

This is related to Amit K. Saha's answer but for me, on one of my Lollipop devices I kept getting null. So I opened up the maps app and I got the screen below asking me to turn on all that jazz to improve my location.

Once I did that once, my device was able to receive the location with just one call to getLastLocation();

I presume then one would have to ask for these permissions on app install for users who may not have used their maps app yet.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!