How to improve performance of google places autocomplete suggestions? - android

I am using google places autocomplete suggestions in my application. It is working fine but i want to improve its performance. When user types a place, it is giving a suggestions after a long delay or sometimes after deleting the last characters. How do i improve it's performance?
Please help me.
Thanks in advance
Here is my code
public class invoice extends Activity
{
AutoCompleteTextView edit_destination;
DownloadTask placesDownloadTask;
DownloadTask placeDetailsDownloadTask;
ParserTask placesParserTask;
ParserTask placeDetailsParserTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.create_invoice_activity);
edit_destination=(AutoCompleteTextView) findViewById(R.id.destination);
edit_destination.setThreshold(1);
edit_destination.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Creating a DownloadTask to download Google Places matching "s"
placesDownloadTask = new DownloadTask(PLACES);
// Getting url to the Google Places Autocomplete api
String url = getAutoCompleteUrl(s.toString());
// Start downloading Google Places
// This causes to execute doInBackground() of DownloadTask class
placesDownloadTask.execute(url);
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
edit_destination.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int index,
long id) {
ListView lv = (ListView) arg0;
SimpleAdapter adapter = (SimpleAdapter) arg0.getAdapter();
HashMap<String, String> hm = (HashMap<String, String>) adapter.getItem(index);
selected_place=hm.get("description");
// Creating a DownloadTask to download Places details of the selected place
placeDetailsDownloadTask = new DownloadTask(PLACES_DETAILS);
// Getting url to the Google Places details api
String url = getPlaceDetailsUrl(hm.get("reference"));
// Start downloading Google Place Details
// This causes to execute doInBackground() of DownloadTask class
placeDetailsDownloadTask.execute(url);
}
});
}
private String getAutoCompleteUrl(String place){
// Obtain browser key from https://code.google.com/apis/console
String key = "YOUR KEY";
// place to be be searched
String input = "input="+place;
// place type to be searched
String types = "types=geocode";
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = input+"&"+types+"&"+sensor+"&"+key;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/place/autocomplete/"+output+"?"+parameters;
return url;
}
private String getPlaceDetailsUrl(String ref){
// Obtain browser key from https://code.google.com/apis/console
String key = "YOUR KEY";
// reference of place
String reference = "reference="+ref;
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = reference+"&"+sensor+"&"+key;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/place/details/"+output+"?"+parameters;
return url;
}
/** A method to download json data from url */
private String downloadUrl(String strUrl) throws IOException{
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try{
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while( ( line = br.readLine()) != null){
sb.append(line);
}
data = sb.toString();
br.close();
}catch(Exception e){
Log.d("Exception while downloading url", e.toString());
}finally{
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches data from url passed
private class DownloadTask extends AsyncTask<String, Void, String>{
private int downloadType=0;
// Constructor
public DownloadTask(int type){
this.downloadType = type;
}
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try{
// Fetching the data from web service
data = downloadUrl(url[0]);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
switch(downloadType){
case PLACES:
// Creating ParserTask for parsing Google Places
placesParserTask = new ParserTask(PLACES);
// Start parsing google places json data
// This causes to execute doInBackground() of ParserTask class
System.out.println(result);
placesParserTask.execute(result);
break;
case PLACES_DETAILS :
// Creating ParserTask for parsing Google Places
placeDetailsParserTask = new ParserTask(PLACES_DETAILS);
// Starting Parsing the JSON string
// This causes to execute doInBackground() of ParserTask class
placeDetailsParserTask.execute(result);
}
}
}
/** A class to parse the Google Places in JSON format */
private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String,String>>>{
int parserType = 0;
public ParserTask(int type){
this.parserType = type;
}
#Override
protected List<HashMap<String, String>> doInBackground(String... jsonData) {
JSONObject jObject;
List<HashMap<String, String>> list = null;
try{
jObject = new JSONObject(jsonData[0]);
switch(parserType){
case PLACES :
PlaceJSONParser placeJsonParser = new PlaceJSONParser();
// Getting the parsed data as a List construct
list = placeJsonParser.parse(jObject);
break;
case PLACES_DETAILS :
PlaceDetailsJSONParser placeDetailsJsonParser = new PlaceDetailsJSONParser();
// Getting the parsed data as a List construct
list = placeDetailsJsonParser.parse(jObject);
}
}catch(Exception e){
Log.d("Exception",e.toString());
}
return list;
}
#Override
protected void onPostExecute(List<HashMap<String, String>> result) {
switch(parserType){
case PLACES :
String[] from = new String[] { "description"};
int[] to = new int[] { android.R.id.text1 };
// Creating a SimpleAdapter for the AutoCompleteTextView
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), result, android.R.layout.simple_list_item_1, from, to);
// Setting the adapter
edit_destination.setAdapter(adapter);
break;
case PLACES_DETAILS :
HashMap<String, String> hm = result.get(0);
// Getting latitude from the parsed data
latitude = Double.parseDouble(hm.get("lat"));
System.out.println(latitude);
// Getting longitude from the parsed data
longitude = Double.parseDouble(hm.get("lng"));
System.out.println(longitude);
Toast.makeText(invoice.this, latitude+","+longitude , Toast.LENGTH_LONG).show();
SharedPreferences pref=getSharedPreferences("LOC", 0);
String S_lat,S_long;
S_lat=pref.getString("LAT", "");
S_long= pref.getString("LONG","");
source_lat=Double.parseDouble(S_lat);
source_long=Double.parseDouble(S_long);
break;
}
}
}

Replace your "addTextChangedListener" method of autocompleteTextView with following code...
edit_destination.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View arg0, int arg1, KeyEvent arg2) {
return false;
}
});
edit_destination.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Creating a DownloadTask to download Google Places matching "s"
if(placesDownloadTask!=null)
{
Log.i("--placesDownloadTask--","progress_status : "+placesDownloadTask.getStatus());
placesDownloadTask.cancel(true);
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
String chterm;
chterm=edit_destination.getText().toString();
Log.i("---final selected text---", ""+chterm);
placesDownloadTask = new DownloadTask(PLACES);
// Getting url to the Google Places Autocomplete api
String url = getAutoCompleteUrl(s.toString());
// Start downloading Google Places
// This causes to execute doInBackground() of DownloadTask class
placesDownloadTask.execute(url);
}
});
Instead of giving call from onTextChanged, give call from afterTextChanged it reduces the number of calls after each character and hence reduces the delays.
Try it out, It may help you lot.

There is another method, as above one didn't work for me.
Replace your 'addTextChangedListener' with this one.
This will create a new timer every time it executes the onTextChanged() method and cancels the earlier assigned timertask.
edit_destination.addTextChangedListener(new TextWatcher() {
Timer timer = new Timer();
int DELAY = 3000;
String chterm;
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Cancel the timer if already running.
timer.cancel();
chterm = s.toString();
// (Optional) Check if length of query is greater than 3
if(s.length() >= 3) {
// Start a new timer and assign a TimerTask to it.
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Log.i("---final selected text---", "" + chterm);
// Getting url to the Google Places Autocomplete api
String url = getAutoCompleteUrl(chterm);
// Creating a DownloadTask to download Google Places matching "s"
placesDownloadTask = new DownloadTask(PLACES);
// Start downloading Google Places
// This causes to execute doInBackground() of DownloadTask class
placesDownloadTask.execute(url);
}
}, DELAY);
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});

Related

How to use Google Places API to search for addresses/places? Android

I want to know how I can use a string to get search results for an address or a place using Google Places API. Currently, I'm using Geocoder to get search results but the results I am getting are not complete or relevant to my current location. Please be a little descriptive because I haven't used Google Places API before. I have read this tutorial
but I can't quiet understand it. I will have a string input from the user in an EditText view and I want to use that string to show a list of matching addresses which are relevant to my current location.
Hi here i'm giving you simple example about autocomplete, if you want you can try other from referring google api site. Just follow few steps. Hope this help you to understand and do your work easily
Step 1.
In you Activity you need to use edit text as text changed listener, then call places api
et_Search.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
placesTask = new PlacesTask();
String[] toPass = new String[2];
toPass[0] = s.toString();
placesTask.execute(toPass);
}
});
Step 2.
here is calling for google places api
// Fetches all places from GooglePlaces AutoComplete Web Service
private class PlacesTask extends AsyncTask<String, Void, String> {
private String val = "";
#Override
protected String doInBackground(String... place) {
// For storing data from web service
String data = "";
// Obtain browser key from https://code.google.com/apis/console
String key = "key="+getResources().getString(R.string.google_server_key);
String input="";
try {
input = "input=" + URLEncoder.encode(place[0], "utf-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
String parameters = input+"&"+key + "&components=country:in";
// Output format +gpsTracker.getLatitude() + "," + gpsTracker.getLongitude() + "&radius=20000
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/place/autocomplete/"+output+"?"+parameters;
try{
// Fetching the data from we service
data = Webservices.ApiCallGet(url);
}catch(Exception e){
Log.d("Background Task", e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Creating ParserTask
parserTask = new ParserTask();
String[] strData = new String[2];
strData[0] = result;
// Starting Parsing the JSON string returned by Web Service
parserTask.execute(strData);
}
}
Step 3. Getting Result
/** A class to parse the Google Places in JSON format */
private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String,String>>>{
JSONObject jObject;
#Override
protected List<HashMap<String, String>> doInBackground(String... jsonData) {
List<HashMap<String, String>> places = null;
PlaceJSONParser placeJsonParser = new PlaceJSONParser();
try{
jObject = new JSONObject(jsonData[0]);
// Getting the parsed data as a List construct
places = placeJsonParser.parse(jObject);
}catch(Exception e){
Log.d("Exception",e.toString());
}
return places;
}
#Override
protected void onPostExecute(List<HashMap<String, String>> result) {
String[] from = new String[] { "description"};
int[] to = new int[] { android.R.id.text1 };
AutoCompleteAdapter adapter = new AutoCompleteAdapter(getBaseContext(), result);
// Setting the adapter
if(adapter != null && result != null )
lv_SearchList.setAdapter(adapter);
}
}
// Fetches latitude & longitude from place id
private class LatLongTask extends AsyncTask<Void, Void, String> {
private HashMap<String, String> placeMap;
private ProgressDialog dialog;
public LatLongTask(HashMap<String, String> placeMap){
this.placeMap = placeMap;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = ProgressDialog.show(SearchActivity.this, "", "Please Wait...",
true, false);
}
#Override
protected String doInBackground(Void... place) {
// For storing data from web service
String data = "";
// Obtain browser key from https://code.google.com/apis/console
String key = "key="+getResources().getString(R.string.google_server_key);
String input="";
try {
input = "placeid=" + URLEncoder.encode(placeMap.get("place_id"), "utf-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
// Building the parameters to the web service
String parameters = input+"&"+key ;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/place/details/"+output+"?"+parameters;
try{
// Fetching the data from we service
data = Webservices.ApiCallGet(url);
}catch(Exception e){
Log.d("Background Task", e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(dialog!= null && dialog.isShowing()){
dialog.dismiss();
}
try {
JSONObject jResult = new JSONObject(result);
if(jResult.getString("status").equals("OK")) {
JSONObject jsonObject = jResult.getJSONObject("result");
JSONObject jGeometry = jsonObject.getJSONObject("geometry");
JSONObject jLocation = jGeometry.getJSONObject("location");
placeMap.put("lat", ""+jLocation.getString("lat"));
placeMap.put("lng", ""+jLocation.getString("lng"));
ArrayList<HashMap<String, String>> mapArrayList = new ArrayList<HashMap<String, String>>();
mapArrayList.add(placeMap);
Intent intent = new Intent();
intent.putExtra("result", mapArrayList);
if (getParent() == null) {
setResult(Activity.RESULT_OK, intent);
} else {
getParent().setResult(Activity.RESULT_OK, intent);
}
finish();
}else{
Utils.toastmessage(SearchActivity.this, "Please try again later.");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Step 4. create this class
public class PlaceJSONParser {
/** Receives a JSONObject and returns a list */
public List<HashMap<String,String>> parse(JSONObject jObject){
JSONArray jPlaces = null;
try {
/** Retrieves all the elements in the 'places' array */
jPlaces = jObject.getJSONArray("predictions");
} catch (JSONException e) {
e.printStackTrace();
}
/** Invoking getPlaces with the array of json object
* where each json object represent a place
*/
return getPlaces(jPlaces);
}
private List<HashMap<String, String>> getPlaces(JSONArray jPlaces){
int placesCount = jPlaces.length();
List<HashMap<String, String>> placesList = new ArrayList<HashMap<String,String>>();
HashMap<String, String> place = null;
/** Taking each place, parses and adds to list object */
for(int i=0; i<placesCount;i++){
try {
/** Call getPlace with place JSON object to parse the place */
place = getPlace((JSONObject)jPlaces.get(i));
placesList.add(place);
} catch (JSONException e) {
e.printStackTrace();
}
}
return placesList;
}
/** Parsing the Place JSON object */
private HashMap<String, String> getPlace(JSONObject jPlace){
HashMap<String, String> place = new HashMap<String, String>();
String id="";
String reference="";
String description="";
String place_id = "";
try {
description = jPlace.getString("description");
id = jPlace.getString("id");
reference = jPlace.getString("reference");
place_id = jPlace.getString("place_id");
place.put("description", description);
place.put("_id",id);
place.put("reference",reference);
place.put("place_id", place_id);
} catch (JSONException e) {
e.printStackTrace();
}
return place;
}
}

Google places autocomplete api is not working

I have tried most probably every tutorial regarding this. But still am not able to get a proper working autocomplete textview. What i want is ,when a user starts typing the textview should suggest proper places with every character being typed.
Here's my code :
public class Directions extends FragmentActivity {
AutoCompleteTextView from,to;
Button direction;
private static final int GPS_ERRORDIALOG_REQUEST = 9001;
GoogleMap mMap;
public ParserTask parserTask;
protected PlacesTask placesTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(servicesOk())
{
setContentView(R.layout.activity_directions);
if(initMap())
{
from = (AutoCompleteTextView) findViewById(R.id.atv_from);
//from.setAdapter(new PlacesAutoCompleteAdapter(this, R.layout.list_item));
from.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
placesTask = new PlacesTask();
placesTask.execute(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
from.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
from.showDropDown();
return false;
}
});
to = (AutoCompleteTextView) findViewById(R.id.atv_to);
//to.setAdapter(new PlacesAutoCompleteAdapter(this, R.layout.list_item));
to.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
placesTask = new PlacesTask();
placesTask.execute(s.toString());
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
to.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
from.showDropDown();
return false;
}
});
direction = (Button) findViewById(R.id.direction);
}
else
{
Toast.makeText(getApplicationContext(), "map not available", Toast.LENGTH_LONG).show();
}
}
else
{
setContentView(R.layout.activity_main);
}
}
/** A method to download json data from url */
private String downloadUrl(String strUrl) throws IOException{
String data = "";
InputStream iStream = null;
HttpURLConnection urlConnection = null;
try{
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while( ( line = br.readLine()) != null){
sb.append(line);
}
data = sb.toString();
br.close();
}catch(Exception e){
Log.d("Exception while downloading url", e.toString());
}finally{
iStream.close();
urlConnection.disconnect();
}
return data;
}
// Fetches all places from GooglePlaces AutoComplete Web Service
private class PlacesTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... place) {
// For storing data from web service
String data = "";
// Obtain browser key from https://code.google.com/apis/console
String key = "key=Api_key";
String input="";
try {
input = "input=" + URLEncoder.encode(place[0], "utf-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
// place type to be searched
String types = "types=geocode";
// Sensor enabled
String sensor = "sensor=false";
// Building the parameters to the web service
String parameters = input+"&"+types+"&"+sensor+"&"+key;
// Output format
String output = "json";
// Building the url to the web service
String url = "https://maps.googleapis.com/maps/api/place/autocomplete/"+output+"?"+parameters;
try{
// Fetching the data from we service
data = downloadUrl(url);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Creating ParserTask
parserTask = new ParserTask();
// Starting Parsing the JSON string returned by Web Service
parserTask.execute(result);
}
}
/** A class to parse the Google Places in JSON format */
private class ParserTask extends AsyncTask<String, Integer, List<HashMap<String,String>>>{
JSONObject jObject;
#Override
protected List<HashMap<String, String>> doInBackground(String... jsonData) {
List<HashMap<String, String>> places = null;
PlaceJSONParser placeJsonParser = new PlaceJSONParser();
try{
jObject = new JSONObject(jsonData[0]);
// Getting the parsed data as a List construct
places = placeJsonParser.parse(jObject);
}catch(Exception e){
Log.d("Exception",e.toString());
}
return places;
}
#Override
protected void onPostExecute(List<HashMap<String, String>> result) {
String[] frm = new String[] { "description"};
int[] t = new int[] { android.R.id.text1 };
// Creating a SimpleAdapter for the AutoCompleteTextView
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), result, android.R.layout.simple_list_item_1, frm, t);
// Setting the adapter
from.setAdapter(adapter);
to.setAdapter(adapter);
}
}
}
You can use a AutoCompletetextView for showing the place names. I did the same below.
class GetPlaces extends AsyncTask<String, Void, ArrayList<String>> {
#Override
// three dots is java for an array of strings
protected ArrayList<String> doInBackground(String... args) {
ArrayList<String> predictionsArr = new ArrayList<String>();
try {
URL googlePlaces = new URL(
// URLEncoder.encode(url,"UTF-8");
"https://maps.googleapis.com/maps/api/place/autocomplete/json?input="
+ URLEncoder.encode(args[0].toString(), "UTF-8")
+ "&types=geocode&language=en&sensor=true&key="+Constant.GOOGLE_API_KEY);
URLConnection tc = googlePlaces.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
tc.getInputStream()));
String line;
StringBuffer sb = new StringBuffer();
// take Google's legible JSON and turn it into one big string.
while ((line = in.readLine()) != null) {
sb.append(line);
}
// turn that string into a JSON object
JSONObject predictions = new JSONObject(sb.toString());
// now get the JSON array that's inside that object
JSONArray ja = new JSONArray(
predictions.getString("predictions"));
for (int i = 0; i < ja.length(); i++) {
JSONObject jo = (JSONObject) ja.get(i);
// add each entry to our array
predictionsArr.add(jo.getString("description"));
}
} catch (IOException e) {
Log.e("YourApp", "GetPlaces : doInBackground", e);
} catch (JSONException e) {
Log.e("YourApp", "GetPlaces : doInBackground", e);
}
return predictionsArr;
}
#Override
protected void onPostExecute(ArrayList<String> result) {
// update the adapter
adapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1);
adapter.setNotifyOnChange(true);
// attach the adapter to auto complete textview
et_destination.setAdapter(adapter);
}
}
I have created a GooglePlaceAutoComplete (source) (Javadoc) widget in the Sprockets library. You can see how I implemented it and/or set up the library in your project and use the widget.
<net.sf.sprockets.widget.GooglePlaceAutoComplete
android:id="#+id/place"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
To get the Place that a user selects, add an OnPlaceClickListener to it.
public void onPlaceClick(AdapterView<?> parent, Prediction place, int position) {
/* do something with the Place */
}

Android autocomplete Google Places suggestions taking delays too long

I implemented in my app google places autocomplete on autocomplete textview.
At first when i was working on that part predictions came up on start of typing but now there is a delay after i start typing. Usually 5 seconds but sometimes over a half of minute !!!
The strange thing is that after i try autocomplete for first time(and wait that delay) and then go back and to autocomplete again the results show WITHOUT THE DELAY !!
I've run trough my code a million times but i just can't see why is that happening.
I've cleaned my project, rebooted my device and did solution on this topic:
How to improve performance of google places autocomplete suggestions?
Here is my code:
onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog);
actvLocations = (AutocompleteTextViewCustom) findViewById(R.id.actvEnterLocation);
actvLocations.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable arg0) {
Log.e("dialog location after text changed", "AFTER");
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String input = "";
// get input text
try {
input = "input=" + URLEncoder.encode(s.toString(), "utf-8"); // !!! check text coding for different counties !!!
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
/**
* activate error screen
*/
}
// set parameters for parsing
String parameters = input + "&" + "types=geocode" + "&" + "sensor=false";
// start places task for getting results from google
placesTask = new PlacesTask(listenerForAutocompleteCompletedTask, "getPredictions");
placesTask.execute(parameters);
}
});
// populate listview with previously browsed locations
ListView listviewPreviouslyBrowsedLocations = (ListView) findViewById(R.id.lvPreviouslyBrowsedLocations);
final ListViewAdapter adapterListview= new ListViewAdapter(context, listPreviouslyBrowsedLocations);
listviewPreviouslyBrowsedLocations.setAdapter(adapterListview);
listviewPreviouslyBrowsedLocations.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View convertView, int position, long arg3) {
List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
list.add(adapterListview.getParameters(position));
listenerForHeaderLocationChange.onLocationChangeExecuteThisMethod(list, false);
dismiss();
}
});
}
OnTaskCompleted listenerForAutocompleteCompletedTask = new OnTaskCompleted() {
#Override
public void onGetAutocompletePredictionsExecuteThisMethod( final List<HashMap<String, String>> listOfHashmapsForAutocompleteTextview) {
//making simple adapter for autocomplete textview
String[] from = new String[] { "description" };
int[] to = new int[] { android.R.id.text1 };
SimpleAdapter adapter = new SimpleAdapter(context, listOfHashmapsForAutocompleteTextview, android.R.layout.simple_dropdown_item_1line, from, to);
actvLocations.setAdapter(adapter);
/** autocomplete textview drop down items wouldn't show even after threshold set to 0 so .showDropDown() forces drop down items to show*/
actvLocations.showDropDown();
actvLocations.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View convertView, final int position, long arg3) {
dismiss();
final PlacesTask taskForLatLng = new PlacesTask(listenerForAutocompleteCompletedTask, "getPlaceLatLng");
#SuppressWarnings("unchecked")
HashMap<String, String> clickedItem = (HashMap<String, String>) parent.getItemAtPosition(position);
// set name of place for getting result back to header
nameOfSelectedPlace = clickedItem.get("description");
taskForLatLng.execute("placeid=" + clickedItem.get("place_id"));
}
});
}
Here is the async task where the delay happends.
I've marked where the delay happends
public class PlacesTask extends AsyncTask<String, Void, String>{
private OnTaskCompleted listener;
String typeOfResult;
String url = null;
public PlacesTask(OnTaskCompleted callerListener, String type) {
this.listener = callerListener;
this.typeOfResult = type;
switch (type) {
case "getPredictions":
url = "https://maps.googleapis.com/maps/api/place/autocomplete/";
break;
case "getPlaceLatLng":
url = "https://maps.googleapis.com/maps/api/place/details/";
break;
}
// this case is if we+re tying to get place name from latlng
if (type.contains(","))
url = "https://maps.googleapis.com/maps/api/geocode/";
}
#Override
protected String doInBackground(String... place) {
Log.e("places task", "usao je tu");
String data = "";
String APIkey = "key=AIzaSyC5gP63PPD8CQLCXqbkZZf6XvOhZPnoe-s";
/**
//place type to be searched
String types = "types=geocode";
// our app didn't use any sensor to determinate the location
String sensor = "sensor=false";
*/
String parameters, outputFormat;
// building paramters for search
parameters = place[0] + "&" + APIkey;
// output format
outputFormat = "json";
try {
// fetching the data from web service
data = downloadUrl(url + outputFormat + "?" + parameters);
} catch(Exception e) {
/**
* activate error screen
*/
}
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// create parser task to parse the gotten results
ParserTask parserTask = new ParserTask(listener, typeOfResult);
// start the parsing
parserTask.execute(result);
}
// private method used in the PlacesTask to download the data from the url
private String downloadUrl(String inputUrl) throws IOException{
String data = "";
InputStream is = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(inputUrl);
//creating http connection to comunicate eith url
urlConnection = (HttpURLConnection) url.openConnection();
Log.e("places task", "3");
/*
*
* HERE IS WHERE THE DELAY HAPPENDS
*/
**urlConnection.connect();**
// reading from url
is = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer sb = new StringBuffer();
String line = "";
while( (line = br.readLine()) != null ) {
sb.append(line);
}
data = sb.toString();
br.close();
} catch (Exception e) {
e.printStackTrace();
/**
* activate error screen
*/
} finally {
is.close();
urlConnection.disconnect();
}
Log.e("places task data", data);
return data;
}
}
i didn't want to post ParserTask and GooglePlacesJSONParser so the question wouldn't be that long but if someone is intereested in those classes just add comment and i will update my question
Please try with this link..
http://wptrafficanalyzer.in/blog/android-autocompletetextview-with-google-places-autocomplete-api/
Onece I did used this Turorial... And Its working properly.
I'm not sure why you are experiencing a delay, possibly it is a network issue or something in the other classes. But if you would like to try a library that provides a GooglePlaceAutoComplete widget, you could take a look at Sprockets (I'm the developer).
After the library is configured with your Google API key, you can add a GooglePlaceAutoComplete element to your layout. For example:
<net.sf.sprockets.widget.GooglePlaceAutoComplete
android:id="#+id/place"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
And then you can get the Place that a user selects by setting an OnPlaceClickListener.
public void onPlaceClick(AdapterView<?> parent, Prediction place, int position) {
/* do something with the Place */
}

Android: How do I parse an HTML page?

I new to android programming. I would like to know how to parse a webpage and extract specific content into a ListView. What is the easiest and best way to do it? Can someone show me an example using what's given below?
URL = "Something.com".
I want to extract the names of the cities and href link for each one.
ann arbor
battle creek
central michigan
detroit metro
flint
grand rapids
Thank you guys and sorry for asking this basic question.
look the code below and let me know if you have any doubts and see this link it may help you
http://wptrafficanalyzer.in/blog/android-lazy-loading-images-and-text-in-listview-from-http-json-data/
public class MainActivity extends Activity {
ListView mListView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// URL to the JSON data
String strUrl = "ur url/countries";
// Creating a new non-ui thread task to download json data
DownloadTask downloadTask = new DownloadTask();
// Starting the download process
downloadTask.execute(strUrl);
// Getting a reference to ListView of activity_main
mListView = (ListView) findViewById(R.id.lv_countries);
}
/** A method to download json data from url */
private String downloadUrl(String strUrl) throws IOException{
String data = "";
InputStream iStream = null;
try{
URL url = new URL(strUrl);
// Creating an http connection to communicate with url
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// Connecting to url
urlConnection.connect();
// Reading data from url
iStream = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
StringBuffer sb = new StringBuffer();
String line = "";
while( ( line = br.readLine()) != null){
sb.append(line);
}
data = sb.toString();
br.close();
}catch(Exception e){
Log.d("Exception while downloading url", e.toString());
}finally{
iStream.close();
}
return data;
}
/** AsyncTask to download json data */
private class DownloadTask extends AsyncTask<String, Integer, String>{
String data = null;
#Override
protected String doInBackground(String... url) {
try{
data = downloadUrl(url[0]);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
#Override
protected void onPostExecute(String result) {
// The parsing of the xml data is done in a non-ui thread
ListViewLoaderTask listViewLoaderTask = new ListViewLoaderTask();
// Start parsing xml data
listViewLoaderTask.execute(result);
}
}
/** AsyncTask to parse json data and load ListView */
private class ListViewLoaderTask extends AsyncTask<String, Void, SimpleAdapter>{
JSONObject jObject;
// Doing the parsing of xml data in a non-ui thread
#Override
protected SimpleAdapter doInBackground(String... strJson) {
try{
jObject = new JSONObject(strJson[0]);
CountryJSONParser countryJsonParser = new CountryJSONParser();
countryJsonParser.parse(jObject);
}catch(Exception e){
Log.d("JSON Exception1",e.toString());
}
// Instantiating json parser class
CountryJSONParser countryJsonParser = new CountryJSONParser();
// A list object to store the parsed countries list
List<HashMap<String, Object>> countries = null;
try{
// Getting the parsed data as a List construct
countries = countryJsonParser.parse(jObject);
}catch(Exception e){
Log.d("Exception",e.toString());
}
// Keys used in Hashmap
String[] from = { "country"
// Ids of views in listview_layout
int[] to = { R.id.tv_country};
// Instantiating an adapter to store each items
// R.layout.listview_layout defines the layout of each item
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), countries, R.layout.lv_layout, from, to);
return adapter;
}
/** Invoked by the Android on "doInBackground" is executed */
#Override
protected void onPostExecute(SimpleAdapter adapter) {
// Setting adapter for the listview
mListView.setAdapter(adapter);
for(int i=0;i<adapter.getCount();i++){
HashMap<String, Object> hm = (HashMap<String, Object>) adapter.getItem(i);
HashMap<String, Object> hmDownload = new HashMap<String, Object>();
hm.put("flag_path",imgUrl);
hm.put("position", i);
}
}
}
#Override
protected void onPostExecute(HashMap<String, Object> result) {
// Getting the path to the downloaded image
String path = (String) result.get("flag");
// Getting the position of the downloaded image
int position = (Integer) result.get("position");
// Getting adapter of the listview
SimpleAdapter adapter = (SimpleAdapter ) mListView.getAdapter();
// Getting the hashmap object at the specified position of the listview
HashMap<String, Object> hm = (HashMap<String, Object>) adapter.getItem(position);
// Overwriting the existing path in the adapter
hm.put("flag",path);
// Noticing listview about the dataset changes
adapter.notifyDataSetChanged();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
Use something like http://jsoup.org/ to get the html content.
Then use something like
http://jsoup.org/cookbook/extracting-data/selector-syntax
extract the urls.
then
:matches(regex): find elements whose text matches the specified regular expression; e.g. div:matches((?i)login)
do a regular expression for the url you are looking for.
I'm not sure if this is what you want.
I remember I did this once and luckily I found that code.
You would just have to give a call to this Intentservice from your activity
and you would need to specify the website name at the top ( in url variable )
public class parser extends IntentService {
public String url="http://www.mywebsite.com";
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
// shutdown();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
return super.onStartCommand(intent, flags, startId);
}
private Timer t = new Timer();
byte[] buffer;
public timeCell() {
super("name");
// TODO Auto-generated constructor stub
}
#Override
protected void onHandleIntent(Intent arg0) {
// TODO Auto-generated method stub
t.schedule(new TimerTask(){
#Override
public void run() {
// TODO Auto-generated method stub
BufferedReader reader=null;
try {
reader = new BufferedReader(
new InputStreamReader(
new URL(url).openStream()));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String line = null;
try {
line = reader.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.v("line was ", line); // printing is done here ;)
}
}

Intent with ListView (JSON data)

I put JSON data to the ListView. I want data in the list("ItemTitle", "ItemText", "latit", "longit", "date") can transfer to another activity(result.java)when item is clicked. Here are the code:
activity:
public class Earthquake extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.earthquake);
getData();
}
private void getData() {
// TODO Auto-generated method stub
ListView list = (ListView)findViewById(R.id.earthquake);
try {
List<News> newes = GetJson.update();
List<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();
for(News news : newes){
HashMap<String, Object> item = new HashMap<String, Object>();
item.put("ItemTitle", news.getPlace());
item.put("ItemText", "Magnitude: "+news.getMag());
item.put("latit", news.getLatit());
item.put("longit", news.getLongit());
item.put("date", news.getTime());
data.add(item);
}
SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.list_earthquake,
new String[]{"ItemTitle", "ItemText", "latit", "longit", "date"},
new int[]{R.id.ItemTitle, R.id.ItemText, R.id.latit, R.id.longit, R.id.date});
list.setAdapter(adapter);
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
//intent
}
});
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
GetJson.java:
public class GetJson {
public static List<News> update() throws Exception, IOException {
// TODO Auto-generated method stub
String path = "http://earthquake.usgs.gov/earthquakes/feed/geojson/all/hour";
HttpURLConnection conn = (HttpURLConnection)new URL(path).openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode() == 200){
InputStream json = conn.getInputStream();
return parseJSON(json);
}
return null;
}
private static List<News> parseJSON(InputStream jsonStream) throws Exception {
// TODO Auto-generated method stub
List<News> list = new ArrayList<News>();
byte[] data = StreamTool.read(jsonStream);
String json = new String(data);
//start decoad JSON
JSONObject jsonObject1 = new JSONObject(json);
String object1 = jsonObject1.getString("features");
JSONArray features = new JSONArray(object1);
for(int i = 0; i < features.length(); i++){
JSONObject object2 = features.getJSONObject(i);
JSONObject properties = object2.getJSONObject("properties");
String place = properties.getString("place");
int mag = properties.getInt("mag");
String time = properties.getString("time");
JSONObject geometry = object2.getJSONObject("geometry");
JSONArray coordinates = geometry.getJSONArray("coordinates");
String longit = coordinates.getString(0);
String latit = coordinates.getString(1);
list.add(new News(mag, longit, latit, place, time));
}
return list;
}
}
News.java:
public class News {
private Integer mag;
private String longit;
private String latit;
private String place, time;
public News(){}
public News(Integer mag, String longit, String latit, String place, String time){
this.mag = mag;
this.longit = longit;
this.latit = latit;
this.place = place;
this.time = time;
}
public Integer getMag(){
return mag;
}
public String getLongit(){
return longit;
}
public String getLatit(){
return latit;
}
public String getPlace(){
return place;
}
public String getTime(){
return time;
}
}
Thanks!!
I suggest you rewrite your SimpleAdapter to extends ArrayAdapter<News>. Creating another List of HasMaps is quite useless and consumes additional memory. Than make your News class implement Parcelable. And in onClick() you call something like:
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
News news = parent.getItem(position);
if (news != null) {
Intent intent = new Intent(...);
intent.put("news", news);
startActivity(intent);
}
}
Always use a non-UI thread to fetch data from servers. Looking at your code it looks like you are using the UI thread to fetch data. You may use AsyncTask and paste the code written in the GetJson class in the doInBackground method of an AsyncTask object.
Now about your problem to pass the clicked list item data to the next activity. You will have to either make the class News implement Parcelable or Serializable interface. implementing these classes allows you to send the custom object data to another activity. The most efficient way is to implement Parcelable.
Check the following links for more details:
http://developer.android.com/reference/android/os/Parcelable.html
http://developer.android.com/reference/java/io/Serializable.html
Hope this explanation helps.

Categories

Resources