0

我需要应用程序启动时的位置。我正在使用 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);
    }
}
4

3 回答 3

1

除非 GoogleApiClient 处于连接状态,否则 API 调用将失败。您请求它在 onStart 中连接并且它是异步连接的。您显然不应该在 onStart 中设置随机延迟,也不应该在 AsyncTask 中这样做,因为这会变得不稳定。

在 onConnected 回调发生时(或之后)进行 API 调用。也许使用条件逻辑,这样如果您的应用程序恢复,则不会再次拨打电话。

于 2014-12-30T01:02:27.487 回答
0

由于这是一个直接的答案,我将在这里发布。

简而言之:请看看我的要点

https://gist.github.com/2022a4d2c21d73f042eb

解释:

GoogleApiClient 成功连接谷歌服务后,一眨眼就无法获取完整信息,请注意。所以基本上,您需要向您想要使用的 API 发出请求(FuseLocation API、Google Fit API ...)。onConnected() 方法是您开始请求的地方。GoogleAPIClient 为您提供的每个 API 都有自己的回调实现方式,您也应该查看文档。因此,请考虑查看我的 Gist 并在可行时提供反馈。

于 2014-12-27T00:38:19.733 回答
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 中,获取您的位置,然后断开连接:

    公共无效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();
    }
    

    }

于 2015-07-15T19:15:59.770 回答