0

アプリの起動時に場所が必要です。LastLocation を取得するために、この tut を fusionlocationapi でフォローしています: 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 にランダムな遅延を入れるべきではありません。

onConnected コールバックの発生時 (または発生後) に API 呼び出しを行います。おそらく条件付きロジックを使用して、アプリが再開された場合に呼び出しが再度行われないようにします。

于 2014-12-30T01:02:27.487 に答える