在应用启动时获取位置地址

时间:2014-12-27 00:12:02

标签: android location google-play-services fusedlocationproviderapi

我需要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);
    }
}

3 个答案:

答案 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)

执行以下操作(顺便说一下,我尝试以正确的格式输入代码,但如果以下内容看起来很邋),则不会感到抱歉):

  1. 在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);
    
  2. 在onStart / onResume中,连接到您的GoogleApiClient:

    mGoogleApiClient.connect();

  3. 在onPause中,断开与GoogleApiClient的连接:

    if (mGoogleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        mGoogleApiClient.disconnect();
    }
    
  4. 在onConnect回调方法中,执行以下操作:

    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,FragmentPostActivity.this);

  5. 在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();
    }
    

    }