【问题标题】:Get location address on app startup在应用启动时获取位置地址
【发布时间】:2014-12-27 00:12:02
【问题描述】:

我需要应用启动时的位置。我正在使用 fusedlocationapi 关注这个 tut 以获取 LastLocation:https://developer.android.com/training/location/retrieve-current.html

当通过按钮执行查找地址的 AsyncTask 时,它工作得很好,但是当我在 oncreate 或 onstart 中放入相同的 sn-p 时,就会得到 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);
    }
}

【问题讨论】:

  • 首先:请在您的 doInBackground 中检查 null。您获取最后一个位置的调用并不能保证它总是返回值。这不是一个好习惯。考虑在 onConmected() 中创建 LocationRequest,并请求位置回调/侦听器并获取您的位置/在 onLocationChanged(Location loc) 中运行您的 getAddress 方法。关于实施,正在播出,请谷歌

标签: android location google-play-services fusedlocationproviderapi


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

    说明:

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

    【讨论】:

      【解决方案3】:

      执行以下操作(顺便说一句,我尝试以正确的格式输入代码,但如果下面看起来很邋遢,那就不用那么抱歉了):

      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(Location location) {

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

        }

      【讨论】:

        猜你喜欢
        • 2011-06-29
        • 2011-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-16
        • 2011-08-01
        • 1970-01-01
        相关资源
        最近更新 更多