我需要app启动时的位置。我使用fusedlocationapi跟随这个tut得到LastLocation:https://developer.android.com/training/location/retrieve-current.html
当通过按钮执行查找地址的AsyncTask时,它工作得很好,但是当我将相同的片段放在oncreate或onstart上时,我正在获得NPE,可能因为它需要很长时间才能进行定位。
我希望加载活动,显示ProgressBar&然后显示位置,而不必单击按钮。
解决方法是在onstart短暂延迟后执行AsyncTask,但我猜测应该有更高效的东西。
public class MainActivity extends ActionBarActivity implements
ConnectionCallbacks, OnConnectionFailedListener{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAddress = (TextView) findViewById(R.id.address);
mActivityIndicator =
(ProgressBar) findViewById(R.id.address_progress);
buildGoogleApiClient();
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
public void onConnected(Bundle connectionHint) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
private class GetAddressTask extends AsyncTask<Location, Void, String>
{
Context mContext;
public GetAddressTask(Context context) {
super();
mContext = context;
}
@Override
protected String doInBackground(Location... params) {
Geocoder geocoder =
new Geocoder(mContext, Locale.getDefault());
// Get the current location from the input parameter list
Location loc = params[0];
// Create a list to contain the result address
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocation(loc.getLatitude(),
loc.getLongitude(), 1);
} catch (IOException e1) {
Log.e("LocationSampleActivity",
"IO Exception in getFromLocation()");
e1.printStackTrace();
return ("IO Exception trying to get address");
} catch (IllegalArgumentException e2) {
// Error message to post in the log
String errorString = "Illegal arguments " +
Double.toString(loc.getLatitude()) +
" , " +
Double.toString(loc.getLongitude()) +
" passed to address service";
Log.e("LocationSampleActivity", errorString);
e2.printStackTrace();
return errorString;
}
// If the reverse geocode returned an address
if (addresses != null && addresses.size() > 0) {
// Get the first address
Address address = addresses.get(0);
/*
* Format the first line of address (if available),
* city, and country name.
*/
String addressText = String.format(
"%s, %s, %s",
// If there's a street address, add it
address.getMaxAddressLineIndex() > 0 ?
address.getAddressLine(0) : "",
// Locality is usually a city
address.getLocality(),
// The country of the address
address.getCountryName());
// Return the text
return addressText;
} else {
return "No address found";
}
}
@Override
protected void onPostExecute(String address) {
// Set activity indicator visibility to "gone"
mActivityIndicator.setVisibility(View.GONE);
// Display the results of the lookup.
mAddress.setText(address);
}
}
public void getAddress(View v) {
// Ensure that a Geocoder services is available
if (Build.VERSION.SDK_INT >=
Build.VERSION_CODES.GINGERBREAD
&&
Geocoder.isPresent()) {
// Show the activity indicator
mActivityIndicator.setVisibility(View.VISIBLE);
/*
* Reverse geocoding is long-running and synchronous.
* Run it on a background thread.
* Pass the current location to the background task.
* When the task finishes,
* onPostExecute() displays the address.
*/
(new GetAddressTask(this)).execute(mLastLocation);
}
}
答案 0 :(得分:1)
除非GoogleApiClient处于连接状态,否则API调用将失败。您要求它在onStart中连接并且它是异步连接的。你显然不应该在onStart中添加一个随机的延迟,你不应该在AsyncTask中这样做,因为它会很不稳定。
在onConnected回调中(或之后)进行API调用。也许使用条件逻辑,这样如果你的应用程序恢复,则不会再次进行调用。
答案 1 :(得分:0)
由于这是一个直接的答案,我将在此发布。
简而言之:请看看我的要点
https://gist.github.com/2022a4d2c21d73f042eb
阐释:
GoogleApiClient成功连接到Google服务后,眨眼无法获取完整信息,您应该知道这一点。基本上,您需要请求您要使用的API(FuseLocation API,Google Fit API ...)。并且onConnected()方法是您启动请求的地方。 GoogleAPIClient为您提供的每个API都有自己的实现回调的方式,您也应该查看文档。因此,请考虑查看我的要点并提供反馈,如果有效的话。
答案 2 :(得分:0)
执行以下操作(顺便说一下,我尝试以正确的格式输入代码,但如果以下内容看起来很邋),则不会感到抱歉):
在onCreate中,设置您的GoogleApiClient:
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10000).setFastestInterval(5000);
在onStart / onResume中,连接到您的GoogleApiClient:
mGoogleApiClient.connect();
在onPause中,断开与GoogleApiClient的连接:
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
在onConnect回调方法中,执行以下操作:
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,FragmentPostActivity.this);
在onLocationChanged中,获取您的位置,然后断开连接:
public void onLocationChanged(位置位置){
mLastLocation = location;
if (mGoogleApiClient.isConnected() && mLastLocation != null) {
Log.e("LocationChanged", String.valueOf(location.getLatitude()) + " Longitude: " + String.valueOf(location.getLongitude()));
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}