Thanh Nam Pham Thanh Nam Pham - 8 days ago 9
Android Question

How to combine Google map and Place API in Android

Im facing the problem about using Google Map and Place in my project. I have tried some days to find out best solution but I'm not yet.

I want to use Goolge map and Place API. My goals is when I input restaurant location into EditText search autocomplete, google map will identify this position, and show other restaurant nearby around by marker.

So, Can I use to combine google map and place to implement and use json to manage the marker?

I know Google service database has apply for user, but there are too much marker and I can not create new and manual

I have refer this link:

https://mapmaker.google.com/mapmaker


But it's not meet demand my requirement

Thank you !

Answer

Code is bit lengthy but not difficult to imlement

  • From Map Fragment initiate places fragment .....

     Fragment fragmentObject = new AutoCompletePlacesFragment();
     Bundle args = new Bundle(2);
     args.putInt("userID", preferedUserId);
     args.putString("passengerGcm", preferedPassengerGcm);
     fragmentObject.setArguments(args);
     android.support.v4.app.FragmentManager fm = getFragmentManager();
     fm.beginTransaction()
                    .replace(R.id.container, fragmentObject)
                    .commit();
    

    Here is placefragment named as AutoCompletePlacesFragment.java (manage your stuff where you find this line * //Do the things here on Click.....*)

    public class AutoCompletePlacesFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, View.OnClickListener {

    private static final LatLngBounds BOUND = new LatLngBounds( new LatLng(-0, 0), new LatLng(0, 0));

    private EditText mAutocompleteView; private RecyclerView mRecyclerView; private LinearLayoutManager mLinearLayoutManager; private PlacesAutoCompleteAdapter mAutoCompleteAdapter; ImageView delete; GoogleApiClient mGoogleApiClient;

View RootView;

int preferedUserId; String preferedPassengerGcm; PreferenceData preferenceData;

public AutoCompletePlacesFragment() { // Required empty public constructor }

@Override public void onCreate(Bundle savedInstanceState) { }

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment buildGoogleApiClient(); RootView =inflater.inflate(R.layout.fragment_auto_complete_places, container, false);

    mAutocompleteView = (EditText) RootView.findViewById(R.id.autocomplete_places);
    mAutocompleteView.setOnClickListener(this);
    delete=(ImageView) RootView.findViewById(R.id.cross);

    mAutoCompleteAdapter =  new PlacesAutoCompleteAdapter(RootView.getContext(), R.layout.searchview_adapter,
            mGoogleApiClient, BOUND, null);

    mRecyclerView=(RecyclerView) RootView.findViewById(R.id.recyclerView);
    mLinearLayoutManager=new LinearLayoutManager(RootView.getContext());
    mRecyclerView.setLayoutManager(mLinearLayoutManager);
    mRecyclerView.setAdapter(mAutoCompleteAdapter);
    delete.setOnClickListener(this);
    mAutocompleteView.addTextChangedListener(new TextWatcher() {

        public void onTextChanged(CharSequence s, int start, int before,
                                  int count) {
            if (!s.toString().equals("") && mGoogleApiClient.isConnected()) {
                mAutoCompleteAdapter.getFilter().filter(s.toString());
            } else if (!mGoogleApiClient.isConnected()) {
                Toast.makeText(RootView.getContext(), getResources().getString(R.string.internet_error), Toast.LENGTH_SHORT).show();
               // Log.e(Constants.PlacesTag,getResources().getString(R.string.internet_error));
            }

        }

        public void beforeTextChanged(CharSequence s, int start, int count,
                                      int after) {

        }

        public void afterTextChanged(Editable s) {

        }
    });
    mRecyclerView.addOnItemTouchListener(
            new AutoCompleteItemClickListener(this, new AutoCompleteItemClickListener.OnItemClickListener() {
                @Override
                public void onItemClick(View view, int position) {
                    final PlacesAutoCompleteAdapter.PlaceAutocomplete item = mAutoCompleteAdapter.getItem(position);
                    final String placeId = String.valueOf(item.placeId);
                    Log.i("TAG", "Autocomplete item selected: " + item.description);
                    /*
                         Issue a request to the Places Geo Data API to retrieve a Place object with additional details about the place.
                     */

                    PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi
                            .getPlaceById(mGoogleApiClient, placeId);
                    placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
                        @Override
                        public void onResult(PlaceBuffer places) {
                            if (!places.getStatus().isSuccess()) {
                                // Request did not complete successfully
                                places.release();
                                return;
                            }
                            if (places.getCount() == 1) {
                                //Do the things here on Click.....
                                Toast.makeText(RootView.getContext(), String.valueOf(places.get(0).getLatLng()), Toast.LENGTH_SHORT).show();
                                Fragment fragmentObject = new PassengerFragmentMap();
                                Bundle args = new Bundle(5);
                                     args.putString("destination",item.description.toString());
                                args.putDouble("destLat", places.get(0).getLatLng().latitude);
                                args.putDouble("destLong",places.get(0).getLatLng().longitude);
                                fragmentObject.setArguments(args);
                                preferenceData.setCurrentCabRequestDestinationPreferences(item.description.toString());
                                android.support.v4.app.FragmentManager fm = getFragmentManager();
                                if(fm!=null) {
                                    fm.beginTransaction()
                                            .replace(R.id.container, fragmentObject)
                                            .commit();
                                }
                            } else {
                                Toast.makeText(RootView.getContext(), getResources().getString(R.string.internet_error), Toast.LENGTH_SHORT).show();
                            }

                        }
                    });
                    Log.i("TAG", "Clicked: " + item.description);
                    Log.i("TAG", "Called getPlaceById to get Place details for " + item.placeId);
                }
            })
    );

    return RootView;

}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {

}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
}

@Override
public void onDetach() {
    super.onDetach();

}

public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}

protected synchronized void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .addApi(Places.GEO_DATA_API)
            .build();
}

@Override
public void onConnected(Bundle bundle) {
    Log.v("Google API Callback", "Connection Done");
}

@Override
public void onConnectionSuspended(int i) {
    Log.v("Google API Callback", "Connection Suspended");
    Log.v("Code", String.valueOf(i));
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Log.v("Google API Callback","Connection Failed");
    Log.v("Error Code", String.valueOf(connectionResult.getErrorCode()));
    Toast.makeText(getActivity(), getResources().getString(R.string.internet_error),Toast.LENGTH_SHORT).show();
}

@Override
public void onClick(View v) {
    if(v==delete){
        mAutocompleteView.setText("");
    }
}

@Override
public void onResume() {
    super.onResume();
    if (!mGoogleApiClient.isConnected() && !mGoogleApiClient.isConnecting()){
        Log.v("Google API","Connecting");
        mGoogleApiClient.connect();
    }
}

public void onLocationSelected(){

}

}

Here is PlacesAutoCompleteAdapter.java (Just copy paste this No need to change)

public class PlacesAutoCompleteAdapter
    extends RecyclerView.Adapter<PlacesAutoCompleteAdapter.PredictionHolder> implements Filterable {

private static final String TAG = "PlacesAutoCompleteAdapter";
private ArrayList<PlaceAutocomplete> mResultList;
private GoogleApiClient mGoogleApiClient;
private LatLngBounds mBounds;
private AutocompleteFilter mPlaceFilter;

private Context mContext;
private int layout;

public PlacesAutoCompleteAdapter(Context context, int resource, GoogleApiClient googleApiClient,
                                 LatLngBounds bounds, AutocompleteFilter filter) {
    mContext = context;
    layout = resource;
    mGoogleApiClient = googleApiClient;
    mBounds = bounds;
    mPlaceFilter = filter;
}

/**
 * Sets the bounds for all subsequent queries.
 */
public void setBounds(LatLngBounds bounds) {
    mBounds = bounds;
}

/**
 * Returns the filter for the current set of autocomplete results.
 */
@Override
public Filter getFilter() {
    Filter filter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();
            // Skip the autocomplete query if no constraints are given.
            if (constraint != null) {
                // Query the autocomplete API for the (constraint) search string.
                mResultList = getAutocomplete(constraint);
                if (mResultList != null) {
                    // The API successfully returned results.
                    results.values = mResultList;
                    results.count = mResultList.size();
                }
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results != null && results.count > 0) {
                // The API returned at least one result, update the data.
                notifyDataSetChanged();
            } else {
                // The API did not return any results, invalidate the data set.
                //notifyDataSetInvalidated();
            }
        }
    };
    return filter;
}

private ArrayList<PlaceAutocomplete> getAutocomplete(CharSequence constraint) {
    if (mGoogleApiClient.isConnected()) {
        Log.i("", "Starting autocomplete query for: " + constraint);

        // Submit the query to the autocomplete API and retrieve a PendingResult that will
        // contain the results when the query completes.
        PendingResult<AutocompletePredictionBuffer> results =
                Places.GeoDataApi
                        .getAutocompletePredictions(mGoogleApiClient, constraint.toString(),
                                mBounds, mPlaceFilter);

        // This method should have been called off the main UI thread. Block and wait for at most 60s
        // for a result from the API.
        AutocompletePredictionBuffer autocompletePredictions = results
                .await(60, TimeUnit.SECONDS);

        // Confirm that the query completed successfully, otherwise return null
        final Status status = autocompletePredictions.getStatus();
        if (!status.isSuccess()) {
            Toast.makeText(mContext, "Error contacting API: " + status.toString(),
                    Toast.LENGTH_SHORT).show();
            Log.e("", "Error getting autocomplete prediction API call: " + status.toString());
            autocompletePredictions.release();
            return null;
        }

        Log.i("", "Query completed. Received " + autocompletePredictions.getCount()
                + " predictions.");

        // Copy the results into our own data structure, because we can't hold onto the buffer.
        // AutocompletePrediction objects encapsulate the API response (place ID and description).

        Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
        ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount());
        while (iterator.hasNext()) {
            AutocompletePrediction prediction = iterator.next();
            // Get the details of this prediction and copy it into a new PlaceAutocomplete object.
            resultList.add(new PlaceAutocomplete(prediction.getPlaceId(),
                    prediction.getDescription()));
        }

        // Release the buffer now that all data has been copied.
        autocompletePredictions.release();

        return resultList;
    }
    Log.e("", "Google API client is not connected for autocomplete query.");
    return null;
}

@Override
public PredictionHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View convertView = layoutInflater.inflate(layout, viewGroup, false);
    PredictionHolder mPredictionHolder = new PredictionHolder(convertView);
    return mPredictionHolder;
}

@Override
public void onBindViewHolder(PredictionHolder mPredictionHolder, final int i) {
    mPredictionHolder.mPrediction.setText(mResultList.get(i).description);
    /*mPredictionHolder.mRow.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mGetLatLonCallback.getLocation(resultList.get(i).toString());
        }
    });*/
}

@Override
public int getItemCount() {
    if(mResultList != null)
        return mResultList.size();
    else
        return 0;
}

public PlaceAutocomplete getItem(int position) {
    return mResultList.get(position);
}

public class PredictionHolder extends RecyclerView.ViewHolder {
    private TextView mPrediction;
    private RelativeLayout mRow;
    public PredictionHolder(View itemView) {

        super(itemView);
        mPrediction = (TextView) itemView.findViewById(R.id.address);
        mRow=(RelativeLayout)itemView.findViewById(R.id.predictedRow);
    }

}

/**
 * Holder for Places Geo Data Autocomplete API results.
 */
public class PlaceAutocomplete {

    public CharSequence placeId;
    public CharSequence description;

    PlaceAutocomplete(CharSequence placeId, CharSequence description) {
        this.placeId = placeId;
        this.description = description;
    }

    @Override
    public String toString() {
        return description.toString();
    }
}

}

Here is AutoCompleteItemClickListener.java (Just copy paste this No need to change)

public class AutoCompleteItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;

public interface OnItemClickListener {
    public void onItemClick(View view, int position);
}

GestureDetector mGestureDetector;

public AutoCompleteItemClickListener(AutoCompletePlacesFragment context, OnItemClickListener listener) {
    mListener = listener;
    mGestureDetector = new GestureDetector(context.getActivity(), new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }
    });
}

@Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
    View childView = view.findChildViewUnder(e.getX(), e.getY());
    if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
        mListener.onItemClick(childView, view.getChildLayoutPosition(childView));
        return true;
    }
    return false;
}

@Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

}

}