Hi!
Today we are going to learn about the Auto-complete location searching feature in Android, In IOS it is very simple. But in android we have to take some effort to do that.
Type and search the location in android very common and mandatory feature for some application. With the help of Google we can achieve this.
Array Adopter to collect data form Google
package XXXX.raj.tot.xxxxxxxxxx.Common;
import android.content.Context;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.Toast;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.places.AutocompleteFilter;
import com.google.android.gms.location.places.AutocompletePrediction;
import com.google.android.gms.location.places.AutocompletePredictionBuffer;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.maps.model.LatLngBounds;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
public class Place_A extends ArrayAdapter<Place_A.PlaceAutocomplete> implements Filterable {
private static final String TAG = "PlaceArrayAdapter";
private GoogleApiClient mGoogleApiClient;
private AutocompleteFilter mPlaceFilter;
private LatLngBounds mBounds;
private ArrayList<PlaceAutocomplete> mResultList;
/** * Constructor * * @param context Context * @param resource Layout resource * @param bounds Used to specify the search bounds * @param filter Used to specify place types */ public Place_A(Context context, int resource, LatLngBounds bounds,
AutocompleteFilter filter) {
super(context, resource);
mBounds = bounds;
mPlaceFilter = filter;
}
public void setGoogleApiClient(GoogleApiClient googleApiClient) {
if (googleApiClient == null || !googleApiClient.isConnected()) {
mGoogleApiClient = null;
} else {
mGoogleApiClient = googleApiClient;
}
}
@Override public int getCount() {
return mResultList.size();
}
@Override public PlaceAutocomplete getItem(int position) {
return mResultList.get(position);
}
private ArrayList<PlaceAutocomplete> getPredictions(CharSequence constraint) {
if (mGoogleApiClient != null) {
Log.i(TAG, "Executing autocomplete query for: " + constraint);
PendingResult<AutocompletePredictionBuffer> results =
Places.GeoDataApi .getAutocompletePredictions(mGoogleApiClient, constraint.toString(),
mBounds, mPlaceFilter);
// Wait for predictions, set the timeout. AutocompletePredictionBuffer autocompletePredictions = results
.await(60, TimeUnit.SECONDS);
final Status status = autocompletePredictions.getStatus();
if (!status.isSuccess()) {
Toast.makeText(getContext(), "Error: " + status.toString(),
Toast.LENGTH_SHORT).show();
Log.e(TAG, "Error getting place predictions: " + status
.toString());
autocompletePredictions.release();
return null;
}
Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount()
+ " predictions.");
Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator();
ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount());
while (iterator.hasNext()) {
AutocompletePrediction prediction = iterator.next();
resultList.add(new PlaceAutocomplete(prediction.getPlaceId(),
prediction.getDescription()));
}
// Buffer release autocompletePredictions.release();
return resultList;
}
Log.e(TAG, "Google API client is not connected.");
return null;
}
@Override public Filter getFilter() {
Filter filter = new Filter() {
@Override protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null) {
// Query the autocomplete API for the entered constraint mResultList = getPredictions(constraint);
if (mResultList != null) {
// 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;
}
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();
}
}
}
Main Class for Search Location
package XXXX.raj.tot.xxxxxxxxxx.Common;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.PlaceBuffer;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import XXXX.raj.cp.helper.JSONParser;
import XXXX.raj.tot.xxxxxxxxxx.Others.URL_Loader;import XXXX.raj.tot.xxxxxxxxxx.R;import XXXX.raj.tot.xxxxxxxxxx.tracking_b.Vehicle_B;
public class PlaceSearch extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
// Google Info private static final String LOG_TAG = "MainActivity";
private static final int GOOGLE_API_CLIENT_ID = 0;
private GoogleApiClient mGoogleApiClient;
private static final LatLngBounds BOUNDS_MOUNTAIN_VIEW = new LatLngBounds(new LatLng(37.398160, -122.180831), new LatLng(37.430610, -121.972090));
// Adoptr abjt private Place_A from_adptr_loc;
// Local var private AutoCompleteTextView aet_from_location, aet_to_location;
EditText et_trking_id;
Spinner spn_trk_num;
CheckBox chbk_is_fav;
Button btn_get_direct;
String F_name, F_address, F_place_ID, F_Lat_Long, T_name, T_address, T_place_ID, T_Lat_Long, Trking_id, Slt_vcl_id, Slt_vcl_nm, Slt_vcl_num;
boolean is_Slted;
ArrayList<Vehicle_B> array_vcl;
ArrayList<String> array_vcl_name;
String rout_for;
@Overrideprotected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_place_search);
rout_for = getIntent().getStringExtra("rout_for");
mGoogleApiClient = new GoogleApiClient.Builder(PlaceSearch.this)
.addApi(Places.GEO_DATA_API)
.enableAutoManage(this, GOOGLE_API_CLIENT_ID, this)
.addConnectionCallbacks(this)
.build();
aet_from_location = (AutoCompleteTextView) findViewById(R.id
.aet_from_location);
aet_from_location.setThreshold(3);
aet_to_location = (AutoCompleteTextView) findViewById(R.id
.aet_to_location);
aet_to_location.setThreshold(3);
btn_get_direct = (Button) findViewById(R.id.btn_get_direct);
et_trking_id = (EditText) findViewById(R.id.et_trking_id);
spn_trk_num = (Spinner) findViewById(R.id.spn_trk_num);
chbk_is_fav = (CheckBox) findViewById(R.id.chbk_is_fav);
aet_from_location.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Place_A.PlaceAutocomplete item = from_adptr_loc.getItem(position);
final String placeId = String.valueOf(item.placeId);
Log.i(LOG_TAG, "Selected: " + item.description);
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi .getPlaceById(mGoogleApiClient, placeId);
placeResult.setResultCallback(from_Loc_mUpdatePlaceDetailsCallback);
Log.i(LOG_TAG, "Fetching details for ID: " + item.placeId);
}
});
from_adptr_loc = new Place_A(this, android.R.layout.simple_list_item_1,
BOUNDS_MOUNTAIN_VIEW, null);
aet_from_location.setAdapter(from_adptr_loc);
aet_to_location.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Place_A.PlaceAutocomplete item = from_adptr_loc.getItem(position);
final String placeId = String.valueOf(item.placeId);
Log.i(LOG_TAG, "Selected: " + item.description);
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi .getPlaceById(mGoogleApiClient, placeId);
placeResult.setResultCallback(to_Loc_mUpdatePlaceDetailsCallback);
Log.i(LOG_TAG, "Fetching details for ID: " + item.placeId);
}
});
aet_to_location.setAdapter(from_adptr_loc);
}
private ResultCallback<PlaceBuffer> to_Loc_mUpdatePlaceDetailsCallback = new ResultCallback<PlaceBuffer>() {
@Override public void onResult(PlaceBuffer places) {
if (!places.getStatus().isSuccess()) {
Log.e(LOG_TAG, "Place query did not complete. Error: " +
places.getStatus().toString());
return;
}
// Selecting the first object buffer. final Place place = places.get(0);
CharSequence attributions = places.getAttributions();
T_name = String.valueOf(Html.fromHtml(place.getName() + ""));
T_address = String.valueOf(Html.fromHtml(place.getAddress() + ""));
T_place_ID = String.valueOf(Html.fromHtml(place.getId() + ""));
T_Lat_Long = String.valueOf(Html.fromHtml(place.getLatLng() + ""));
/* mNameTextView.setText(Html.fromHtml(place.getName() + "")); mAddressTextView.setText(Html.fromHtml(place.getAddress() + "")); mIdTextView.setText(Html.fromHtml(place.getId() + "")); mPhoneTextView.setText(Html.fromHtml(place.getPhoneNumber() + "")); mWebTextView.setText(place.getWebsiteUri() + ""); if (attributions != null) { mAttTextView.setText(Html.fromHtml(attributions.toString())); }*/ }
};
private ResultCallback<PlaceBuffer> from_Loc_mUpdatePlaceDetailsCallback = new ResultCallback<PlaceBuffer>() {
@Override public void onResult(PlaceBuffer places) {
if (!places.getStatus().isSuccess()) {
Log.e(LOG_TAG, "Place query did not complete. Error: " +
places.getStatus().toString());
return;
}
// Selecting the first object buffer. final Place place = places.get(0);
CharSequence attributions = places.getAttributions();
F_name = String.valueOf(Html.fromHtml(place.getName() + ""));
F_address = String.valueOf(Html.fromHtml(place.getAddress() + ""));
F_place_ID = String.valueOf(Html.fromHtml(place.getId() + ""));
F_Lat_Long = String.valueOf(Html.fromHtml(place.getLatLng() + ""));
/* mNameTextView.setText(Html.fromHtml(place.getName() + "")); mAddressTextView.setText(Html.fromHtml(place.getAddress() + "")); mIdTextView.setText(Html.fromHtml(place.getId() + "")); mPhoneTextView.setText(Html.fromHtml(place.getPhoneNumber() + "")); mWebTextView.setText(place.getWebsiteUri() + ""); if (attributions != null) { mAttTextView.setText(Html.fromHtml(attributions.toString())); }*/ }
};
@Overridepublic void onConnected(Bundle bundle) {
from_adptr_loc.setGoogleApiClient(mGoogleApiClient);
Log.i(LOG_TAG, "Google Places API connected.");
}
@Overridepublic void onConnectionFailed(ConnectionResult connectionResult) {
Log.e(LOG_TAG, "Google Places API connection failed with error code: " + connectionResult.getErrorCode());
Toast.makeText(this,
"Google Places API connection failed with error code:" +
connectionResult.getErrorCode(),
Toast.LENGTH_LONG).show();
}
@Overridepublic void onConnectionSuspended(int i) {
from_adptr_loc.setGoogleApiClient(null);
Log.e(LOG_TAG, "Google Places API connection suspended.");
}
private class GeocoderHandler extends Handler {
@Override public void handleMessage(Message message) {
String locationAddress;
switch (message.what) {
case 1:
Bundle bundle = message.getData();
locationAddress = bundle.getString("address");
break;
default:
locationAddress = null;
}
Toast.makeText(getApplicationContext(), locationAddress, Toast.LENGTH_LONG).show();
}
}
}
View for the above Activity
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal">
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_margin="5dp" android:background="@color/wt" android:gravity="center" android:orientation="vertical" android:weightSum="85">
<LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="20" android:orientation="horizontal">
<LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal">
<AutoCompleteTextView android:id="@+id/aet_from_location" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_centerHorizontal="true" android:hint="From Location" />
</LinearLayout>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="20" android:orientation="horizontal">
<AutoCompleteTextView android:id="@+id/aet_to_location" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_centerHorizontal="true" android:hint="To Location" />
</LinearLayout>
<LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="15" android:orientation="horizontal">
<EditText android:id="@+id/et_trking_id" android:layout_width="fill_parent" android:layout_height="fill_parent" android:hint="TRUCKING ID" />
</LinearLayout>
<LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="15" android:orientation="horizontal" android:weightSum="100">
<LinearLayout android:layout_width="0dp" android:layout_height="fill_parent" android:layout_weight="60" android:gravity="center" android:orientation="horizontal" android:padding="2dp">
<Spinner android:id="@+id/spn_trk_num" android:layout_width="fill_parent" android:layout_height="fill_parent" />
</LinearLayout>
<LinearLayout android:layout_width="0dp" android:layout_height="fill_parent" android:layout_weight="40" android:gravity="center" android:orientation="horizontal" android:padding="2dp">
<CheckBox android:id="@+id/chbk_is_fav" android:layout_width="fill_parent" android:layout_height="fill_parent" android:checked="false" android:text="Add To Favorite" />
</LinearLayout>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="15" android:orientation="horizontal">
<Button android:id="@+id/btn_get_direct" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_margin="3dp" android:background="@color/orng" android:text="Get Direction" android:textColor="@color/wt" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
Add Permission to your Manifest file
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<!--The ACCESS_COARSE/FINE_LOCATION permissions are not required to use Google Maps Android API v2, but are recommended. --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
<meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" />
Thats All..,
Please Leave Your Comment..,
Have A Great Day..,