Reputation: 847
I am new to Android development.
I'am struggling a while to autocomplete the userinput. I need a google maps like auto-completion for the user input. The user need to be select a address, place, street a.s.o. from the auto complete and i need the LatLng of it.
I tried to get this done by using the google course but this is not exactly what i want. I don't wanna have a whole fragment or something what is used only for selecting a place, I'm looking for a AutoCompleteTextView
solution. Is there a easy to understand way to do this?
I found this but this looks not like the "normal way" to do this or are i'm wrong? This is a web API call instead of a Android API call isn't it?
--------------------------------UPDATE-----------------------------
My manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="aaeu.app">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<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"/>
<uses-library android:name="com.google.android.maps" />
<application
android:name="com.activeandroid.app.Application"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".presentationlayer.MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".presentationlayer.AlertDetailActivity"
android:screenOrientation="portrait"/>
<meta-data
android:name="AA_DB_NAME"
android:value="local_test_db.db" />
<meta-data
android:name="AA_DB_VERSION"
android:value="9" />
<meta-data
android:name="AA_MODELS"
android:value="aaeu.app.datalayer.Alert , aaeu.app.datalayer.Area" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="XXXXXXBsWU9seEWmlB-CMc_pxZ358b4-esTNR5I" />
<!-- without this meta-data below the app don't crash but sais API key wrong -->
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="XXXXXXBsWU9seEWmlB-CMc_pxZ358b4-esTNR5I" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version"/>
</application>
</manifest>
Upvotes: 2
Views: 50971
Reputation: 11
The Google Play Services version of the Places SDK for Android (in Google Play Services 16.0.0) is deprecated as of January 29, 2019, and will be turned off on July 29, 2019.
Now how we use the **Sreehari** answers with new modifications?
If any one know the solution then let me know.Currently i used the android autocomplete search process.But still struggling for migrating my old autocomplete places search to new one.
Upvotes: -1
Reputation: 1354
Just Stuck With Google's Places Autocomplete Just Do the Following if you want it like AutoCompleteTextView.its MODE_OVERLAY option.
Intent intent = new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_OVERLAY)
.build(mActivity);
startActivityForResult(intent, REQUEST_CODE_AUTOCOMPLETE);
Upvotes: 2
Reputation: 5655
Use this to create custom Places Suggestion and process the data. Below is the Activity which shows Places Suggestion in an AutoCompleteTextView
public class MainActivity extends AppCompatActivity implements
GoogleApiClient.OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks {
private static final String LOG_TAG = "MainActivity";
private static final int GOOGLE_API_CLIENT_ID = 0;
private AutoCompleteTextView mAutocompleteTextView;
private TextView mNameTextView;
private TextView mAddressTextView;
private TextView mIdTextView;
private TextView mPhoneTextView;
private TextView mWebTextView;
private TextView mAttTextView;
private GoogleApiClient mGoogleApiClient;
private PlaceArrayAdapter mPlaceArrayAdapter;
private static final LatLngBounds BOUNDS_MOUNTAIN_VIEW = new LatLngBounds(
new LatLng(37.398160, -122.180831), new LatLng(37.430610, -121.972090));
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient = new GoogleApiClient.Builder(MainActivity.this)
.addApi(Places.GEO_DATA_API)
.enableAutoManage(this, GOOGLE_API_CLIENT_ID, this)
.addConnectionCallbacks(this)
.build();
mAutocompleteTextView = (AutoCompleteTextView) findViewById(R.id
.autoCompleteTextView);
mAutocompleteTextView.setThreshold(3);
mNameTextView = (TextView) findViewById(R.id.name);
mAddressTextView = (TextView) findViewById(R.id.address);
mIdTextView = (TextView) findViewById(R.id.place_id);
mPhoneTextView = (TextView) findViewById(R.id.phone);
mWebTextView = (TextView) findViewById(R.id.web);
mAttTextView = (TextView) findViewById(R.id.att);
mAutocompleteTextView.setOnItemClickListener(mAutocompleteClickListener);
mPlaceArrayAdapter = new PlaceArrayAdapter(this, android.R.layout.simple_list_item_1,
BOUNDS_MOUNTAIN_VIEW, null);
mAutocompleteTextView.setAdapter(mPlaceArrayAdapter);
}
private AdapterView.OnItemClickListener mAutocompleteClickListener
= new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final PlaceArrayAdapter.PlaceAutocomplete item = mPlaceArrayAdapter.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(mUpdatePlaceDetailsCallback);
Log.i(LOG_TAG, "Fetching details for ID: " + item.placeId);
}
};
private ResultCallback<PlaceBuffer> 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();
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()));
}
}
};
@Override
public void onConnected(Bundle bundle) {
mPlaceArrayAdapter.setGoogleApiClient(mGoogleApiClient);
Log.i(LOG_TAG, "Google Places API connected.");
}
@Override
public 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();
}
@Override
public void onConnectionSuspended(int i) {
mPlaceArrayAdapter.setGoogleApiClient(null);
Log.e(LOG_TAG, "Google Places API connection suspended.");
}
}
The filter Adapter required and can be customized according to requirement goes like below
public class PlaceArrayAdapter
extends ArrayAdapter<PlaceArrayAdapter.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 PlaceArrayAdapter(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();
}
}
}
Go through the below link which explains each line
Tutorial with steps explained for Places Suggestion
Upvotes: 10