1

Я пытаюсь создать карту с виджетами PlaceAutocomplete, наложенными на него. Функция этого представления заключается в вычислении расстояния от моего текущего местоположения до местоположения, которое я выбрал в виджета PlaceAutocomplete.PlaceAutocomplete Widget on MapView Fragment

Чтобы объяснить себя лучше, мне нужен такой же фрагмент, как и в приложении Google Maps. Пока я создал фрагмент, который отображает карту. Этот вид затем накладывается виджлом PlaceAutocomplete.

В настоящее время я могу получить свое текущее местоположение, когда я начинаю просмотр карты. (снимок экрана 1) Однако, когда я пытаюсь найти место назначения (снимок экрана 2), виджет просто показывает выбранный вами пункт назначения, не вызывая API Google Directions API, чтобы получить маршрут маршрута от моего местоположения до места назначения. (скриншот 3)

Из моего логарифма я вижу, что метод создания URL-адреса и вызова API 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&region=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()); 
    } 
} 

Может кто-то пожалуйста, помогите мне с этим вопросом?

Любая помощь приветствуется :)

Screenshot 1

Screenshot 2

Screenshot 3

Edit: Этот фрагмент является частью вкладками приложения, так что я не могу использовать активность вместо фрагмент. Поэтому в фрагменте необходимо создать вид mapview и PlaceAutocomplete Widget. Я также хотел бы, чтобы виджет PlaceAutocomplete накладывал карту. Я нашел обучающие программы с виджетами PlaceAutocomplete в отдельном упражнении. Это не то решение, которое я ищу.

ответ

3

Для всех вас, имеющих ту же проблему, мне удалось реализовать проект, на который я намеревался, однако я использовал настраиваемый автокомплексTextView и привязал его к API Google Адресов. Это позволило мне создать запрос и получить ответ.

Ниже приведен код для всех тех храбрых душ, которые хотят создать вызов API Google PlaceAutoComplete, наложенного на карту.

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&region=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); 

    } 
} 

Удачи и не забывайте голосовать вверх пожалуйста, если этот ответ помог вам :)