Pass Latitude and Longitude to Google API Places S

2020-03-30 05:15发布

I have literally been searching for this for weeks. I am a novice java programmer but I have been able to piece together an app that can use a double latitude and longitude hard coded in the same class. It will show a list of current places surrounding those points. I have another separate class with a method that is able to get the current location based on the gps/network but I can't pass the variables created from this second class to the PlaceRequest class. I have looked through all of the tutorials on the above subjects but there isn't anything combining current location and place search results. I have two getters declared but can't call the variables in these. Again sort of a rookie so may be an easy fix. Any ideas?

Update - Here is my code so far: GooglePlaceActivity.java

    public class GooglePlaceActivity extends Activity {
/** Called when the activity is first created. */
Button btn1;
TextView txt1;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setContentView(R.layout.main);
    btn1 = (Button)findViewById(R.id.button1);
    txt1 = (TextView)findViewById(R.id.textView1);
    btn1.setOnClickListener(l);     
}

private class SearchSrv extends AsyncTask<Void, Void, PlacesList>{

    @Override
    protected PlacesList doInBackground(Void... params) {

        PlacesList pl = null;
        try {
            pl = new PlaceRequest().performSearch();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return pl;
    }

    @Override
    protected void onPostExecute(PlacesList result) {

        String text = "Result \n";

        if (result!=null){
            for(Place place: result.results){
                text = text + place.name +"\n";
            }
            txt1.setText(text);
        }
        setProgressBarIndeterminateVisibility(false);
    }
}

View.OnClickListener l = new View.OnClickListener() {   

    @Override

    public void onClick(View v) {
        // TODO Auto-generated method stub

        SearchSrv srv = new SearchSrv();
        setProgressBarIndeterminateVisibility(true);
        srv.execute();          

    }
};

}

//////////////////////

PlaceRequest.java

    public class PlaceRequest {

private static final HttpTransport transport = new ApacheHttpTransport();

private static final String API_KEY = "keyhere";
private static final String LOG_KEY = "GGPlace";
// The different Places API endpoints.
private static final String PLACES_SEARCH_URL =  "https://maps.googleapis.com/maps/api/place/search/json?";
private static final String PLACES_AUTOCOMPLETE_URL = "https://maps.googleapis.com/maps/api/place/autocomplete/json?";
private static final String PLACES_DETAILS_URL = "https://maps.googleapis.com/maps/api/place/details/json?";

private static final boolean PRINT_AS_STRING = true;


//double latitude;
//double longitude;

CurrentLocation clo = new CurrentLocation(null);
//clo.onLocationChanged(latitude);
//double longitude = CurrentLocation.getLongitude();
//double latitude = CurrentLocation.getLatitude();
double longi = clo.getLongitude();
double lat = clo.getLatitude();

public PlacesList performSearch() throws Exception {

    try {
        //CurrentLocation currlo = new CurrentLocation();
        //double lat = currlo.getLatitude();
        //double longi = currlo.getLongitude();
        Log.v(LOG_KEY, "Start Search");
        GenericUrl reqUrl = new GenericUrl(PLACES_SEARCH_URL);
        reqUrl.put("key", API_KEY);
        //reqUrl.put("location", latitude + "," + longitude);
        //reqUrl.put("location", getLatitude(latitude) + "," + getLongitude());
        reqUrl.put("location", lat + "," + longi);
        reqUrl.put("radius", 1600);
        reqUrl.put("types", "food");
        reqUrl.put("sensor", "false");
        Log.v(LOG_KEY, "url= " + reqUrl);
        HttpRequestFactory httpRequestFactory = createRequestFactory(transport);
        HttpRequest request = httpRequestFactory.buildGetRequest(reqUrl);

            Log.v(LOG_KEY, request.execute().parseAsString());                          
            PlacesList places = request.execute().parseAs(PlacesList.class);
            Log.v(LOG_KEY, "STATUS = " + places.status);
            for (Place place : places.results) {
                Log.v(LOG_KEY, place.name);             

            }
            return places;

    } catch (HttpResponseException e) {
        Log.v(LOG_KEY, e.getResponse().parseAsString());
        throw e;
    }

    catch (IOException e) {
        // TODO: handle exception
        throw e;
    }
}

public static HttpRequestFactory createRequestFactory(final HttpTransport transport) {

      return transport.createRequestFactory(new HttpRequestInitializer() {
       public void initialize(HttpRequest request) {
        GoogleHeaders headers = new GoogleHeaders();
        headers.setApplicationName("Google-Places-DemoApp");
        request.setHeaders(headers);
        JsonHttpParser parser = new JsonHttpParser(new JacksonFactory()) ;
        //JsonHttpParser.builder(new JacksonFactory());
        //parser.jsonFactory = new JacksonFactory();
        request.addParser(parser);
       }
    });
}

}

///////////// CurrentLocation.java

    public class CurrentLocation {

    private static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 1; // in Meters
    private static final long MINIMUM_TIME_BETWEEN_UPDATES = 1000; // in Milliseconds

    LocationManager locationManager ;
    double latitude=0;
    double longitude=0;


    public CurrentLocation(Context ctxt) {
super();
locationManager = (LocationManager) ctxt.getSystemService(Context.LOCATION_SERVICE);

// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 
        MINIMUM_TIME_BETWEEN_UPDATES,
        MINIMUM_DISTANCE_CHANGE_FOR_UPDATES, 
        new LocationListener() {

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {}

            @Override
            public void onProviderEnabled(String provider) {}

            @Override
            public void onProviderDisabled(String provider) {}

            @Override
            public void onLocationChanged(Location location) {
                longitude = location.getLongitude();
                latitude = location.getLatitude();

            }
        });

    }
    public double getLatitude() {
return latitude;
    }
    public double getLongitude() {
return longitude;
    } 
    }

1条回答
不美不萌又怎样
2楼-- · 2020-03-30 06:16

Edit: After looking your complete code, I see a few fundamental design flaws so I'm going to show you how I did it and you can adapt it to your program flow. Please keep in mind that this example is vastly simplified from my original, but it should be enough to get you going.

First, the CurrentLocation.java file. My design decision for wrapping this in a Future was so that I can re-use it in multiple activities with the added bonus of killing it when necessary.

public class CurrentLocation implements Callable<Location> {

  private static final String TAG = "CurrentLocation";
  private Context context;
  private LocationManager lm;
  private Criteria criteria;
  private Location bestResult;
  private boolean locationListenerWorking;


  public CurrentLocation(Context context) {
    lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
    this.context = context;
    criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    bestResult = null;
    locationListenerWorking = false;
  }


  public Location call() {
    return getLoc();
  }


  private Location getLoc() {
    String provider = lm.getBestProvider(criteria, true);
    if (provider != null) {
      Log.d(TAG, "Using provider: " +provider);
      locationListenerWorking = true;
      lm.requestLocationUpdates(provider,
                                0,
                                0,
                                singeUpdateListener,
                                context.getMainLooper());
    } else {
      Log.w(TAG, "Couldn't find a location provider");
      return null;
    }



    while (locationListenerWorking) {
      // Check for the interrupt signal - terminate if necessary
      if (Thread.currentThread().isInterrupted()) {
        Log.i(TAG, "User initiated interrupt (cancel signal)");
        cleanup();
        break;
      }

      try {
        // ghetto implementation of a busy wait...
        Thread.sleep(500); // Sleep for half a second
      } catch (Exception e) {
        Log.d(TAG, "Thread interrupted..");
        cleanup();
        break;
      }
    }

    return bestResult;
  }




  private void cleanup() {
    if (lm != null) {
      Log.d(TAG, "Location manager not null - cleaning up");
      lm.removeUpdates(singeUpdateListener);
    } else {
      Log.d(TAG, "Location manager was NULL - no cleanup necessary");
    }
  }




  /**
   * This one-off {@link LocationListener} simply listens for a single location
   * update before unregistering itself.  The one-off location update is
   * returned via the {@link LocationListener} specified in {@link
   * setChangedLocationListener}.
   */
  private LocationListener singeUpdateListener = new LocationListener() {
      public void onLocationChanged(Location location) {
        Log.d(TAG, "Got a location update");
        if (location == null) {
          Log.d(TAG, "Seems as if we got a null location");
        } else {
          bestResult = location;
        }

        cleanup();
        locationListenerWorking = false;
      }

      public void onStatusChanged(String provider, int status, Bundle extras) {}
      public void onProviderEnabled(String provider) {}    
      public void onProviderDisabled(String provider) {}
    };

}

Then in your calling class (i.e. where you need the lat/lon coordinates - you want to do this from an Activity):

private class GetLocationTask extends AsyncTask <Void, Void, Location> {
  private Future<Location> future;
  private ExecutorService executor = new ScheduledThreadPoolExecutor(5);
  private boolean cancelTriggered = false;

  protected void onPreExecute() {
    Log.d(TAG, "Starting location get...");
  }

  public Location doInBackground(Void... arg) {
    CurrentLocation currLoc = new CurrentLocation(getApplicationContext());
    future = executor.submit(currLoc);
    long LOCATION_TIMEOUT = 20000; // ms = 20 sec
    try {
      // return future.get(Constants.LOCATION_TIMEOUT, TimeUnit.MILLISECONDS);
      return future.get(LOCATION_TIMEOUT, TimeUnit.MILLISECONDS);
    } catch (Exception e) {
      Log.w(TAG, "Location get timed out");
      future.cancel(true);
      return null;
    }
  }

  public boolean killTask() {
    cancelTriggered = true;
    boolean futureCancelRes = future.cancel(true);
    this.cancel(true);
    Log.d(TAG, "Result of cancelling task: " +futureCancelRes);
    return futureCancelRes;
  }


  protected void onPostExecute(Location res) {
    if (cancelTriggered) {
      Log.d(TAG, "User initiated cancel - this is okay");
      cancelTriggered = false;
    } else if (res == null) {
      Log.d(TAG, "Could not get a location result");
    } else {
      double lat = res.getLatitude();
      double lon = res.getLongitude();
      Log.d(TAG, "Latitude: " +lat);
      Log.d(TAG, "Longitude: " +lon);
    }
  }
}

Finally to wrap things up, here's how you call it:

GetLocationTask t = new GetLocationTask();
t.execute();

And if you need to kill the location update for whatever reason (if your user switches out of your activity, etc), this will kill the AsyncTask as well as the associated Future task.

t.killTask();

P.S. You may want to get your API keys changed and edit it out of your post.

查看更多
登录 后发表回答