getLastLocation 返回一个空值
Posted
技术标签:
【中文标题】getLastLocation 返回一个空值【英文标题】:getLastLocation returns a null value 【发布时间】:2015-10-09 21:23:58 【问题描述】:我已遵循本指南https://developer.android.com/training/location/retrieve-current.html#permissions,但我无法收到最后一个位置。
我只需要一次该位置。
这是我的代码:
public class MainActivity extends ActionBarActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener
public static final String TAG = MainActivity.class.getSimpleName();
public static final String DAILY_FORECAST = "DAILY_FORECAST";
public static final String HOURLY_FORECAST = "HOURLY_FORECAST";
private Forecast mForecast;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
private double mLatitude;
private double mLongitude;
@Bind(R.id.timeLabel) TextView mTimeLabel;
@Bind(R.id.temperatureLabel) TextView mTemperatureLabel;
@Bind(R.id.humidityValue) TextView mHumidityValue;
@Bind(R.id.precipValue) TextView mPrecipValue;
@Bind(R.id.summaryLabel) TextView mSummaryLabel;
@Bind(R.id.iconImageView) ImageView mIconImageView;
@Bind(R.id.refreshImageView) ImageView mRefreshImageView;
@Bind(R.id.progressBar) ProgressBar mProgressBar;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mProgressBar.setVisibility(View.INVISIBLE);
buildGoogleApiClient();
//mLatitude = 37.8267;
//mLongitude = -122.423;
mRefreshImageView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
getForecast(mLatitude, mLongitude);
);
getForecast(mLatitude, mLongitude);
private void getForecast(double latitude, double longitude)
String apiKey = "48fb6c0ca3567d0b17bf99b400ef5606";
String forecastUrl = "https://api.forecast.io/forecast/" + apiKey +
"/" + latitude + "," + longitude;
if (isNetworkAvailable())
toggleRefresh();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecastUrl)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback()
@Override
public void onFailure(Request request, IOException e)
runOnUiThread(new Runnable()
@Override
public void run()
toggleRefresh();
);
alertUserAboutError();
@Override
public void onResponse(Response response) throws IOException
runOnUiThread(new Runnable()
@Override
public void run()
toggleRefresh();
);
try
String jsonData = response.body().string();
Log.v(TAG, jsonData);
if (response.isSuccessful())
mForecast = parseForecastDetails(jsonData);
runOnUiThread(new Runnable()
@Override
public void run()
updateDisplay();
);
else
alertUserAboutError();
catch (IOException e)
Log.e(TAG, "Exception caught: ", e);
catch (JSONException e)
Log.e(TAG, "Exception caught: ", e);
);
else
Toast.makeText(this, getString(R.string.network_unavailable_message),
Toast.LENGTH_LONG).show();
private void toggleRefresh()
if (mProgressBar.getVisibility() == View.INVISIBLE)
mProgressBar.setVisibility(View.VISIBLE);
mRefreshImageView.setVisibility(View.INVISIBLE);
else
mProgressBar.setVisibility(View.INVISIBLE);
mRefreshImageView.setVisibility(View.VISIBLE);
private void updateDisplay()
Current current = mForecast.getCurrent();
mTemperatureLabel.setText(current.getTemperature() + "");
mTimeLabel.setText("At " + current.getFormattedTime() + " it will be");
mHumidityValue.setText(current.getHumidity() + "");
mPrecipValue.setText(current.getPrecipChance() + "%");
mSummaryLabel.setText(current.getSummary());
Drawable drawable = getResources().getDrawable(current.getIconId());
mIconImageView.setImageDrawable(drawable);
private Forecast parseForecastDetails(String jsonData) throws JSONException
Forecast forecast = new Forecast();
forecast.setCurrent(getCurrentDetails(jsonData));
forecast.setHourlyForecast(getHourlyForecast(jsonData));
forecast.setDailyForecast(getDailyForecast(jsonData));
return forecast;
private Day[] getDailyForecast(String jsonData) throws JSONException JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
JSONObject daily = forecast.getJSONObject("daily");
JSONArray data = daily.getJSONArray("data");
Day[] days = new Day[data.length()];
for (int i = 0; i < data.length(); i++)
JSONObject jsonDay = data.getJSONObject(i);
Day day = new Day();
day.setSummary(jsonDay.getString("summary"));
day.setIcon(jsonDay.getString("icon"));
day.setTime(jsonDay.getLong("time"));
day.setTemperatureMax(jsonDay.getDouble("temperatureMax"));
day.setTimezone(timezone);
days[i] = day;
return days;
private Hour[] getHourlyForecast(String jsonData) throws JSONException
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
JSONObject hourly = forecast.getJSONObject("hourly");
JSONArray data = hourly.getJSONArray("data");
Hour[] hours = new Hour[data.length()];
for (int i = 0; i < data.length(); i++)
JSONObject jsonHour = data.getJSONObject(i);
Hour hour = new Hour();
hour.setSummary(jsonHour.getString("summary"));
hour.setTemperature(jsonHour.getDouble("temperature"));
hour.setIcon(jsonHour.getString("icon"));
hour.setTime(jsonHour.getLong("time"));
hour.setTimezone(timezone);
hours[i] = hour;
return hours;
private Current getCurrentDetails(String jsonData) throws JSONException
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
Log.i(TAG, "From JSON: " + timezone);
JSONObject currently = forecast.getJSONObject("currently");
Current current = new Current();
current.setHumidity(currently.getDouble("humidity"));
current.setTime(currently.getInt("time"));
current.setSummary(currently.getString("summary"));
current.setTemperature(currently.getInt("temperature"));
current.setIcon(currently.getString("icon"));
current.setPrecipChance(currently.getDouble("precipProbability"));
current.setTimeZone(timezone);
Log.d(TAG, current.getFormattedTime());
return current;
private boolean isNetworkAvailable()
ConnectivityManager manager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if (networkInfo != null && networkInfo.isConnected())
isAvailable = true;
return isAvailable;
private void alertUserAboutError()
AlertDialogFragment dialog = new AlertDialogFragment();
dialog.show(getFragmentManager(), "error_dialog");
@OnClick (R.id.dailyButton)
public void startDailyActivity(View view)
Intent intent = new Intent(this, DailyForecastActivity.class);
intent.putExtra(DAILY_FORECAST, mForecast.getDailyForecast());
startActivity(intent);
@OnClick(R.id.hourlyButton)
public void startHourlyActivity(View view)
Intent intent = new Intent(this, HourlyForecastActivity.class);
intent.putExtra(HOURLY_FORECAST, mForecast.getHourlyForecast());
startActivity(intent);
protected synchronized void buildGoogleApiClient()
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
@Override
public void onConnected(Bundle bundle)
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null)
mLatitude = mLastLocation.getLatitude();
mLongitude = mLastLocation.getLongitude();
@Override
public void onConnectionSuspended(int i)
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
`
【问题讨论】:
获取经纬度的代码在哪里??可以分享一下吗 1- 确保您已连接到 Google Play 服务 因为它可以...问了无数次...做一些研究... 【参考方案1】:getLastLocation()
很容易返回 null。它也不会请求新的位置,所以即使你得到一个位置,它也可能很旧,并且不能反映当前位置。最好注册一个监听器,即使您在收到第一个 onLocationChanged() 回调后取消注册。
这个问题被问了很多,通常被标记为questions like this one的重复
但是,在您的情况下,您似乎也只是忘记致电connect()
:
buildGoogleApiClient();
mGoogleApiClient.connect(); //added
您可以使用this answer中的代码作为注册位置回调的参考,如果您想获得准确的当前位置,建议您这样做。
编辑:由于您只需要一个位置,这里是该代码的略微修改版本,它请求位置更新,然后在第一个位置进入后取消注册位置更新。
public class MainActivity extends Activity implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
private double mLatitude;
private double mLongitude;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildGoogleApiClient();
mGoogleApiClient.connect();
@Override
protected void onPause()
super.onPause();
if (mGoogleApiClient != null)
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
protected synchronized void buildGoogleApiClient()
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
@Override
public void onConnected(Bundle bundle)
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
//mLocationRequest.setSmallestDisplacement(0.1F);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
@Override
public void onConnectionSuspended(int i)
Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show();
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show();
@Override
public void onLocationChanged(Location location)
mLastLocation = location;
//no need to do a null check here:
mLatitude = location.getLatitude();
mLongitude = location.getLongitude();
//remove location updates if you just need one location:
if (mGoogleApiClient != null)
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
【讨论】:
“getLastLocation() 有很高的返回 null 的倾向。”:在什么情况下即使位置设置为 ON,此 API 也会返回 null? @SantoshSalunke 在这里更好的解释:***.com/a/32291415/4409409 谢谢丹尼尔。在我的 Nexus-5 上,我观察到 getLastLocation 即使在我启动 Google Map 应用程序然后再次启动我的应用程序之后也会返回 null。即使在 Google 地图应用程序中正确检测到位置,getLastLocation API 也会返回 null。我不明白:如果谷歌地图请求了位置,那么为什么缓存的位置没有更新。以上是关于getLastLocation 返回一个空值的主要内容,如果未能解决你的问题,请参考以下文章
从 Settings Api 对话框打开位置后,getLastLocation() 返回 null
getLastLocation() 返回俄罗斯中部的随机位置
来自 LocationClient 的 getLastLocation() 始终返回 null [重复]
Android studio 不检查 mFusedLocationProviderClient.getLastLocation().addOnSuccessListener 并返回当前位置 null
Android LocationClient.getLastLocation() 返回带有新时间戳的旧且不准确的位置
FusedLocationApi.getLastLocation 总是返回 null(android 6.0,api 23)