Create Project
Create new project in Android Studio with steps as below:
Step 1: Input Project Name and Select Project Location
Step 2: Select SDK for Android App
Step 3: Select Default Activity for App
Step 4: Finish create project
Google Map API
Login to https://console.developers.google.com and create Places API key for testing. Create new xml file named google_maps_api.xml in res/values folder contains Places API key:
AIzaSyB9MxxJBmzLHdfsMEZSdV0vORR_MRwirPI
Add Library as Dependencies
Open build.gradle file in Gradle Scripts and add new library as below:
implementation 'com.google.android.gms:play-services-maps:15.0.1'
implementation 'com.google.android.gms:play-services-location:15.0.1'
implementation 'com.google.api-client:google-api-client:1.23.0'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.google.code.gson:gson:2.6.2'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
implementation 'com.squareup.okhttp3:okhttp:3.4.1'
Add Strings
Open res\values\strings.xml file and add new string as below:
<resources>
<string name="app_name">Learn Android with Real Apps</string>
<string name="input_your_place">Input your place...</string>
</resources>
Manifest Permissions
Open AndroidManifest.xml file in manifest folder, add permissions and google map api as below:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.demo.learnandroidwithrealapps">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="@string/google_maps_key" />
</application>
</manifest>
Create Entities
Create new package named entities. In this package, create new entities as below:
Term
Create new java class named Term.java as below:
package android.demo.entities;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
public class Term implements Serializable {
@SerializedName("offset")
private int offset;
@SerializedName("value")
private String value;
public int getOffset() {
return this.offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
}
MatchedSubstring
Create new java class named MatchedSubstring.java as below:
package android.demo.entities;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
public class MatchedSubstring implements Serializable {
@SerializedName("length")
private int length;
@SerializedName("offset")
private int offset;
public int getLength() {
return this.length;
}
public void setLength(int length) {
this.length = length;
}
public int getOffset() {
return this.offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
}
Prediction
Create new java class named Prediction.java as below:
package android.demo.entities;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
import java.util.List;
public class Prediction implements Serializable {
@SerializedName("description")
private String description;
@SerializedName("id")
private String id;
@SerializedName("matched_substrings")
private List matchedSubstrings;
@SerializedName("place_id")
private String placeId;
@SerializedName("reference")
private String reference;
@SerializedName("terms")
private List<Term> terms;
@SerializedName("types")
private List<String> types;
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public List<MatchedSubstring> getMatchedSubstrings() {
return this.matchedSubstrings;
}
public void setMatchedSubstrings(List<MatchedSubstring> matchedSubstrings) {
this.matchedSubstrings = matchedSubstrings;
}
public String getPlaceId() {
return this.placeId;
}
public void setPlaceId(String placeId) {
this.placeId = placeId;
}
public String getReference() {
return this.reference;
}
public void setReference(String reference) {
this.reference = reference;
}
public List<Term> getTerms() {
return this.terms;
}
public void setTerms(List<Term> terms) {
this.terms = terms;
}
public List<String> getTypes() {
return this.types;
}
public void setTypes(List<String> types) {
this.types = types;
}
}
Predictions
Create new java class named Predictions.java as below:
package android.demo.entities;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class Predictions {
@SerializedName("status")
private String status;
@SerializedName("predictions")
private List<Prediction> predictions;
public String getStatus() {
return this.status;
}
public void setStatus(String status) {
this.status = status;
}
public List<Prediction> getPredictions() {
return this.predictions;
}
public void setPredictions(List<Prediction> predictions) {
this.predictions = predictions;
}
}
Custom Places Layout
Select res\layout folder. In this folder, create new layout named place_row_layout.xml as below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textViewName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
Custom Adapter
Create new package named adapters. In this package, create new java class named PlacesAutoCompleteAdapter.java as below:
package android.demo.adapters;
import android.content.Context;
import android.demo.api.APIClient;
import android.demo.api.GoogleMapAPI;
import android.demo.entities.Prediction;
import android.demo.entities.Predictions;
import android.demo.learnandroidwithrealapps.R;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class PlacesAutoCompleteAdapter extends ArrayAdapter<Prediction> {
private Context context;
private List<Prediction> predictions;
public PlacesAutoCompleteAdapter(Context context, List<Prediction> predictions) {
super(context, R.layout.place_row_layout, predictions);
this.context = context;
this.predictions = predictions;
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view = LayoutInflater.from(context).inflate(R.layout.place_row_layout, null);
if (predictions != null && predictions.size() > 0) {
Prediction prediction = predictions.get(position);
TextView textViewName = view.findViewById(R.id.textViewName);
textViewName.setText(prediction.getDescription());
}
return view;
}
@NonNull
@Override
public Filter getFilter() {
return new PlacesAutoCompleteFilter(this, context);
}
private class PlacesAutoCompleteFilter extends Filter {
private PlacesAutoCompleteAdapter placesAutoCompleteAdapter;
private Context context;
public PlacesAutoCompleteFilter(PlacesAutoCompleteAdapter placesAutoCompleteAdapter, Context context) {
super();
this.placesAutoCompleteAdapter = placesAutoCompleteAdapter;
this.context = context;
}
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
try {
placesAutoCompleteAdapter.predictions.clear();
FilterResults filterResults = new FilterResults();
if (charSequence == null || charSequence.length() == 0) {
filterResults.values = new ArrayList<Prediction>();
filterResults.count = 0;
} else {
GoogleMapAPI googleMapAPI = APIClient.getClient().create(GoogleMapAPI.class);
Predictions predictions = googleMapAPI.getPlacesAutoComplete(charSequence.toString(), "geocode", "en", context.getString(R.string.google_maps_key)).execute().body();
filterResults.values = predictions.getPredictions();
filterResults.count = predictions.getPredictions().size();
}
return filterResults;
} catch (Exception e) {
return null;
}
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
placesAutoCompleteAdapter.predictions.clear();
placesAutoCompleteAdapter.predictions.addAll((List<Prediction>) filterResults.values);
placesAutoCompleteAdapter.notifyDataSetChanged();
}
@Override
public CharSequence convertResultToString(Object resultValue) {
Prediction prediction = (Prediction) resultValue;
return prediction.getDescription();
}
}
}
Retrofit API
Create new package named api. In this package, create new api as below:
APIClient
Create new java class named APIClient.java as below:
package android.demo.api;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class APIClient {
private static Retrofit retrofit = null;
public static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
retrofit = new Retrofit.Builder()
.baseUrl("https://maps.googleapis.com/maps/api/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
}
GoogleMapAPI
Create new interface named GoogleMapAPI.java as below:
package android.demo.api;
import android.demo.entities.Predictions;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface GoogleMapAPI {
@GET("place/autocomplete/json")
public Call<Predictions> getPlacesAutoComplete(
@Query("input") String input,
@Query("types") String types,
@Query("language") String language,
@Query("key") String key
);
}
Main Activity Layout
Open res\layout\activity_main.xml file and create layout as below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<AutoCompleteTextView
android:id="@+id/autoCompleteTextViewPlace"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/input_your_place" />
</LinearLayout>
Main Activity Class
Add code to MainActivity.java file in android.demo.learnandroidwithrealapps package as below:
package android.demo.learnandroidwithrealapps;
import android.demo.adapters.PlacesAutoCompleteAdapter;
import android.demo.entities.Prediction;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.AutoCompleteTextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private AutoCompleteTextView autoCompleteTextViewPlace;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
autoCompleteTextViewPlace = findViewById(R.id.autoCompleteTextViewPlace);
loadData();
}
private void loadData() {
List<Prediction> predictions = new ArrayList<>();
PlacesAutoCompleteAdapter placesAutoCompleteAdapter = new PlacesAutoCompleteAdapter(getApplicationContext(), predictions);
autoCompleteTextViewPlace.setThreshold(1);
autoCompleteTextViewPlace.setAdapter(placesAutoCompleteAdapter);
}
}
Structure of Project
Run App
Load Main Activity
Input Keyword
Select A Result