我正在尝试创建一个叠加有PlaceAutocomplete小部件的mapview。
该视图的功能是计算从当前位置到我在PlaceAutocomplete小部件中选择的位置的距离。
为了更好地说明自己,我需要与Google Maps应用类似的片段。目前,我已经创建了一个显示地图的片段。然后,该视图被PlaceAutocomplete小部件覆盖。
目前,我可以在启动地图视图时获取当前位置。 (屏幕截图1)但是,当我尝试搜索目的地时(屏幕截图2),该小部件仅显示了我选择的目的地,而没有调用Google Directions API来获取从我的位置到目的地的公交路线。 (屏幕截图3)
从我的logcat中,我可以看到甚至没有调用构造URL并调用Google Directions API的方法。
这是我的代码:
public class GeoFragment extends Fragment implements PlaceSelectionListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
GoogleMap map;
SupportMapFragment mapFragment;
private LocationRequest lr;
private GoogleApiClient apiClient;
private static View view;
private Location location;
int PLACE_AUTOCOMPLETE_REQUEST_CODE = 1;
int RESULT_OK = 2;
int RESULT_CANCELED = 3;
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
final String GOOGLE_KEY;
int PLACE_PICKER_REQUEST = 1;
double currentLatitude;
double currentLongitude;
SupportPlaceAutocompleteFragment searcher;
String placeString;
public GeoFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
buildGoogleApiClient();
if (view != null) {
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null)
parent.removeView(view);
}
try {
view = inflater.inflate(R.layout.layout_map, container, false);
mapFragment = ((SupportMapFragment) this.getChildFragmentManager().findFragmentById(R.id.mapView));
searcher = (SupportPlaceAutocompleteFragment) this.getChildFragmentManager().findFragmentById(R.id.info_text);
//searcher.setBoundsBias(new LatLngBounds(new LatLng(), new LatLng()));
map = mapFragment.getMap();
map.getUiSettings().setAllGesturesEnabled(true);
map.getUiSettings().setMyLocationButtonEnabled(true);
map.setMyLocationEnabled(true);
map.getUiSettings().setZoomControlsEnabled(false);
map.animateCamera(CameraUpdateFactory.zoomIn());
map.animateCamera(CameraUpdateFactory.zoomTo(15), 2000, null);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(currentLatitude, currentLongitude), 19));
MapsInitializer.initialize(this.getActivity());
} catch (InflateException e) {
Toast.makeText(getActivity(), "Problems inflating the view !",
Toast.LENGTH_LONG).show();
} catch (NullPointerException e) {
Log.e("GServices Error", e.toString());
}
return view;
}
protected synchronized void buildGoogleApiClient() {
apiClient = new GoogleApiClient.Builder(getActivity().getApplicationContext())
.addApi(LocationServices.API)
.addApi(Places.GEO_DATA_API)
.addApi(Places.PLACE_DETECTION_API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(getActivity().getApplicationContext());
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, getActivity(), PLAY_SERVICES_RESOLUTION_REQUEST).show();
}
return false;
}
return true;
}
@Override
public void onStart() {
super.onStart();
if (apiClient != null) {
apiClient.connect();
}
}
@Override
public void onStop() {
super.onStop();
if (apiClient.isConnected()) {
apiClient.disconnect();
}
}
@Override
public void onPause() {
super.onPause();
stopLocationUpdates();
}
@Override
public void onResume() {
super.onResume();
checkPlayServices();
// Resuming the periodic location updates
if (apiClient.isConnected()) {
startLocationUpdates();
}
}
protected void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(
apiClient, lr, this);
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
apiClient, this);
}
public void getCoordinates(){
location = LocationServices.FusedLocationApi.getLastLocation(apiClient);
if (location != null) {
currentLatitude = location.getLatitude();
currentLongitude = location.getLongitude();
}
}
@Override
public void onLocationChanged(Location loc) {
location = loc;
getCoordinates();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(currentLatitude, currentLongitude), 19));
}
@Override
public void onConnected(Bundle connectionHint) {
if (location == null) {
lr = LocationRequest.create();
lr.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
lr.setInterval(1000);
LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, lr, this);
}
//getCoordinates();
}
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.i("Map Connection Failed", "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
public void onConnectionSuspended(int arg0) {
apiClient.connect();
}
public void SearchPlace(String place) throws GooglePlayServicesNotAvailableException, GooglePlayServicesRepairableException {
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
startActivityForResult(builder.build(getActivity()), PLACE_PICKER_REQUEST);
callPlaces(currentLongitude, currentLatitude, place);
}
public void callPlaces(final double longitude, final double latitude, final String destination) {
String tag_string_req = "req_places";
String url = "https://maps.googleapis.com/maps/api/directions/json?origin=" + latitude + "," + longitude + "&destination="+ destination +"&alternatives=true&mode=transit®ion=mt&key=" + getResources().getString(R.string.google_places_key);
StringRequest strReq = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
drawPath(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("Error", "Registration Error: " + error.getMessage());
Toast.makeText(getActivity().getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
}
});
AppController.getInstance().addToRequestQueue(strReq);
}
public void drawPath(String result){
try {
final JSONObject jsonObject = new JSONObject(result);
JSONArray routeArray = jsonObject.getJSONArray("routes");
JSONObject routes = routeArray.getJSONObject(0);
JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
String encodedString = overviewPolylines.getString("points");
String statusString = jsonObject.getString("status");
Log.d("test: ", encodedString);
List<LatLng> list = decodePoly(encodedString);
LatLng last = null;
for (int i = 0; i < list.size()-1; i++) {
LatLng src = list.get(i);
LatLng dest = list.get(i+1);
last = dest;
Log.d("Last latLng:", last.latitude + ", " + last.longitude );
Polyline line = map.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude), new LatLng(dest.latitude, dest.longitude))
.width(4)
.color(Color.GREEN));
}
Log.d("Last latLng:", last.latitude + ", " + last.longitude );
}catch (JSONException e){
e.printStackTrace();
}
catch(ArrayIndexOutOfBoundsException e) {
System.err.println("Caught ArrayIndexOutOfBoundsException: "+ e.getMessage());
}
}
private List<LatLng> decodePoly(String encoded){
List<LatLng> poly = new ArrayList<LatLng>();
int index = 0;
int length = encoded.length();
int latitude = 0;
int longitude = 0;
while(index < length){
int b;
int shift = 0;
int result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
int destLat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
latitude += destLat;
shift = 0;
result = 0;
do {
b = encoded.charAt(index++) - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b > 0x20);
int destLong = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
longitude += destLong;
poly.add(new LatLng((latitude / 1E5),(longitude / 1E5) ));
}
return poly;
}
@Override
public void onPlaceSelected(Place place) {
Log.i("Destination", "Place Selected: " + place.getName());
placeString = place.getName().toString();
CharSequence attributions = place.getAttributions();
if (!TextUtils.isEmpty(attributions)) {
try {
SearchPlace(placeString);
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
}
} else {
searcher.setText("Where shall we take you today?");
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
searcher.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onError(Status status) {
Log.e("TAG", "onError: Status = " + status.toString());
}
}
有人可以帮我解决这个问题吗?
任何帮助表示赞赏:)
编辑:此片段是选项卡式应用程序的一部分,因此我不能使用活动代替片段。因此,需要在片段中构造mapview和PlaceAutocomplete Widget。我还想让PlaceAutocomplete小部件覆盖地图。我发现在单独的活动中有PlaceAutocomplete小部件的教程。这不是我要寻找的解决方案。
最佳答案
对于遇到相同问题的所有人,我已经设法实现了我想要的项目,但是我使用了自定义的AutoCompleteTextView并将其附加到Google Places API。这使我能够创建请求并获得响应。
以下是所有希望创建对Google PlaceAutoComplete API的调用的勇敢者的代码,这些代码覆盖在地图上。
public class GeoFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
GoogleMap map;
SupportMapFragment mapFragment;
AutoCompleteTextView destination;
GooglePlacesAutocompleteAdapter mAdapter;
ListView listView;
String dest;
private LocationRequest lr;
private GoogleApiClient apiClient;
private static View view;
private Location location;
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
final String GOOGLE_KEY;
double currentLatitude;
double currentLongitude;
private static final String[] LOCATION_PERMS={
Manifest.permission.ACCESS_FINE_LOCATION
};
public GeoFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (!canAccessLocation() || !canAccessLocation()) {
requestPermissions(LOCATION_PERMS, LOCATION_REQUEST);
}
buildGoogleApiClient();
if (view != null) {
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null)
parent.removeView(view);
}
try {
view = inflater.inflate(R.layout.layout_map, container, false);
mapFragment = ((SupportMapFragment) this.getChildFragmentManager().findFragmentById(R.id.mapView));
destination = (AutoCompleteTextView) view.findViewById(R.id.destinationTextView);
final CardView destinationCard = (CardView)view.findViewById(R.id._Cardview);
final CardView placesCard = (CardView)view.findViewById(R.id._cardPlaces);
mAdapter = new GooglePlacesAutocompleteAdapter(this.getActivity(), android.R.layout.simple_list_item_1);
listView = (ListView) view.findViewById(R.id.placeList);
listView.setAdapter(mAdapter);
listView.setTextFilterEnabled(true);
destination.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
placesCard.setVisibility(View.VISIBLE);
mAdapter.getFilter().filter(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
dest = (String) parent.getItemAtPosition(position);
destination.setText(dest);
dest = dest.replace(" ", "%20");
try {
SearchPlace(dest);
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
}
placesCard.setVisibility(View.INVISIBLE);
destinationCard.setVisibility(View.INVISIBLE);
}
});
map = mapFragment.getMap();
map.getUiSettings().setAllGesturesEnabled(true);
map.getUiSettings().setMyLocationButtonEnabled(true);
map.setMyLocationEnabled(true);
map.getUiSettings().setZoomControlsEnabled(false);
map.animateCamera(CameraUpdateFactory.zoomIn());
map.animateCamera(CameraUpdateFactory.zoomTo(15), 2000, null);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(currentLatitude, currentLongitude), 19));
MapsInitializer.initialize(this.getActivity());
} catch (InflateException e) {
Toast.makeText(getActivity(), "Problems inflating the view !",
Toast.LENGTH_LONG).show();
} catch (NullPointerException e) {
Log.e("GServices Error", e.toString());
}
return view;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch(requestCode) {
case LOCATION_REQUEST:
if (canAccessLocation()) {
callLocationPerms();
}
break;
}
}
private void callLocationPerms() {
Toast.makeText(getActivity().getApplicationContext(),
"We need your permission to access you current location", Toast.LENGTH_SHORT).show();
}
private boolean canAccessLocation() {
return(hasPermission(Manifest.permission.ACCESS_FINE_LOCATION));
}
@TargetApi(Build.VERSION_CODES.M)
private boolean hasPermission(String perm) {
return(PackageManager.PERMISSION_GRANTED==getActivity().checkSelfPermission(perm));
}
protected synchronized void buildGoogleApiClient() {
apiClient = new GoogleApiClient.Builder(getActivity().getApplicationContext())
.addApi(LocationServices.API)
.addApi(Places.GEO_DATA_API)
.addApi(Places.PLACE_DETECTION_API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(getActivity().getApplicationContext());
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, getActivity(), PLAY_SERVICES_RESOLUTION_REQUEST).show();
}
return false;
}
return true;
}
public void getCoordinates(){
location = LocationServices.FusedLocationApi.getLastLocation(apiClient);
if (location != null) {
currentLatitude = location.getLatitude();
currentLongitude = location.getLongitude();
}
}
@Override
public void onLocationChanged(Location loc) {
location = loc;
getCoordinates();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(currentLatitude, currentLongitude), 19));
}
@Override
public void onConnected(Bundle connectionHint) {
if (location == null) {
lr = LocationRequest.create();
lr.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
lr.setInterval(1000);
LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, lr, this);
}
//getCoordinates();
}
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.i("Map Connection Failed", "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
public void onConnectionSuspended(int arg0) {
apiClient.connect();
}
public void SearchPlace(String place) throws GooglePlayServicesNotAvailableException, GooglePlayServicesRepairableException {
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
//startActivityForResult(builder.build(getActivity()), PLACE_PICKER_REQUEST);
callPlaces(currentLongitude, currentLatitude, place);
}
public void callPlaces(final double longitude, final double latitude, final String destination) {
String tag_string_req = "req_places";
String url = "https://maps.googleapis.com/maps/api/directions/json?origin=" + latitude + "," + longitude + "&destination="+ destination +"&alternatives=false&mode=transit®ion=mt&key=" + getResources().getString(R.string.google_places_key);
StringRequest strReq = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
parsePlace(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("Error", "Registration Error: " + error.getMessage());
Toast.makeText(getActivity().getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
}
});
AppController.getInstance().addToRequestQueue(strReq);
}
}
祝您好运,如果此答案对您有所帮助,请别忘了投票:)