How can I extract string from OnPostExecute to my Main Activity - android

I'm still NEW, i repeat, NEW in android studio and I'm trying to display place name,vicinity,lat and long using listview. I already got listview ready but I couldnt get the string from the OnPostExecute. I tried using this https://stackoverflow.com/a/12575319/5776859 but It did not work at all, or maybe I didnt do it correctly. I hope anyone could help me or show me the proper way to get the string and double from the OnPostExecute.
public class PlacesDisplayTask extends AsyncTask<Object, Integer,
List<HashMap<String,String>>> {
JSONObject googlePlacesJson;
GoogleMap googleMap;
#Override
public List<HashMap<String, String>> doInBackground(Object... inputObj) {
List<HashMap<String, String>> googlePlacesList = null;
Places placeJsonParser = new Places();
try {
googleMap = (GoogleMap) inputObj[0];
googlePlacesJson = new JSONObject((String) inputObj[1]);
googlePlacesList = placeJsonParser.parse(googlePlacesJson);
} catch (Exception e) {
Log.d("Exception", e.toString());
}
return googlePlacesList;
}
#Override
protected void onPostExecute(List<HashMap<String,String>> list) {
for (int i = 0; i < 3; i++) {
HashMap<String, String> googlePlace = list.get(i);
double lat = Double.parseDouble(googlePlace.get("lat"));
double lng = Double.parseDouble(googlePlace.get("lng"));
String placeName = googlePlace.get("place_name");
String vicinity = googlePlace.get("vicinity");
}
}
}

Use interfaces like this
public class PlacesDisplayTask extends AsyncTask<Object, Integer,
List<HashMap<String,String>>> {
public AsyncResponse delegate = null;
JSONObject googlePlacesJson;
GoogleMap googleMap;
#Override
public List<HashMap<String, String>> doInBackground(Object... inputObj) {
List<HashMap<String, String>> googlePlacesList = null;
Places placeJsonParser = new Places();
try {
googleMap = (GoogleMap) inputObj[0];
googlePlacesJson = new JSONObject((String) inputObj[1]);
googlePlacesList = placeJsonParser.parse(googlePlacesJson);
} catch (Exception e) {
Log.d("Exception", e.toString());
}
return googlePlacesList;
}
#Override
protected void onPostExecute(List<HashMap<String,String>> list) {
delegate.processFinish(list);
}
}
and your activity should handle the response by implementing the interface's method
public class MainActivity implements AsyncResponse{
PlacesDisplayTask asyncTask =new PlacesDisplayTask ();
#Override
public void onCreate(Bundle savedInstanceState) {
//this to set delegate/listener back to this class
asyncTask.delegate = this;
//execute the async task
asyncTask.execute();
}
//this override the implemented method from asyncTask
void processFinish(List<HashMap<String,String>> list){
//Here you will receive the result fired from async class
//of onPostExecute(result) method.
for (int i = 0; i < 3; i++) {
HashMap<String, String> googlePlace = list.get(i);
double lat = Double.parseDouble(googlePlace.get("lat"));
double lng = Double.parseDouble(googlePlace.get("lng"));
String placeName = googlePlace.get("place_name");
String vicinity = googlePlace.get("vicinity");
}
}
}
Create an interface like this
public interface AsyncResponse {
void processFinish(List<HashMap<String,String>> list);
}

A less tedious way to accomplish what you're trying to do is to perform whatever task that requires the returned value within onPostExecute(). You can input most references like context using a constructor and store them as global variables to use.
Another way can be to set the return type in the signature of the class to List<HashMap<String, String>> and you can call <PlacesDisplayTask object>.execute().get() method. But this will make the background process synchronous i.e. it will block the UI thread, waiting on the result.
The last alternative that I can think of involves the use of a delegate as described in the link you've already posted.

Related

Return LatLng object from nested asynctask

I have spent days on this, but I can't find a solution to my problem:
I'm developing an app that retrieves a list of theaters showing some movie selected by the user, parsing an HTML page in an AsyncTask.
I want to visualize those theaters on a Map with markers, so I need coordinates: once the "GetCinemaList" AsyncTask is completed, I try to populate my markerList in onPostExecute.
I have an SQLite db in which I store [theater|city|lat|lng]. So I first look up in the db, if it is not found I want call another AsyncTask to retrieve coordinates from HTTP google geocoding ('cause device geocoder returns null, causing the app to crash)
The problem is I am not able to return the LatLng point to the first AsyncTask...
I have tried to use listeners and to override processFinish(LatLng p), but I can't assign the value to my variable cause, accessing it from inner class it should be final.
Any help/idea? Thanks!
Here my code (containing error) for the AsyncTasks , in my Activity.
private class GetCinemaList extends AsyncTask<URL, Void, List<String>> {
private Context mContext;
public GetCinemaList(Context c){
mContext = c;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected List<String> doInBackground(URL... urls) {
List<String> cinemas = new ArrayList<>();
Document docHTML = null;
try {
docHTML = QueryUtils.makeRequest(urls[0]);
cinemas = QueryUtils.extractCinemasFromHTML(mTitile, docHTML);
} catch (IOException e) {
Log.e("JSwa", "Problem making request for parsing HTML "+e);
}
return cinemas;
}
#Override
protected void onPostExecute(List<String> result) {
super.onPostExecute(result);
cinemaList = result;
LatLng point;
pointList = new ArrayList<>();
for (String elem : cinemaList) {
String name = elem.split("\t")[0];
String orari = elem.split("\t")[1];
Cursor cursor = queryDB(mCinemaDbR, city, name);
if (!cursor.moveToFirst()) {
// call geocoding service
new LatLongFromService(name.concat(" " + city), new AsyncResponse() {
#Override
public void processFinish(LatLng output) {
point = output;
}
}).execute();
Log.d("JSwa", "Inserting point "+point.toString());
// insert new value in the database
long id = addCimena(mCinemaDbW, name, city, String.valueOf(point.latitude), String.valueOf(point.longitude));
// insert new value in the list
MarkerOptions marker = new MarkerOptions().position(point).title(name).snippet(orari);
pointList.add(marker);
}
else{
double lat = Double.parseDouble(cursor.getString(cursor.getColumnIndex(CinemaEntry.COLUMN_LAT)));
double lng = Double.parseDouble(cursor.getString(cursor.getColumnIndex(CinemaEntry.COLUMN_LNG)));
MarkerOptions marker = new MarkerOptions().position(new LatLng(lat,lng)).title(name)
.snippet(orari);
pointList.add(marker);
}
cursor.close();
}
for (MarkerOptions marker : pointList){
m_map.addMarker(marker);
}
}
}
// Sometimes happens that device gives location = null
public class LatLongFromService extends AsyncTask<Void, Void, StringBuilder> {
String place;
public AsyncResponse delegate = null;
public LatLongFromService(String place, AsyncResponse resp) {
this.place = place;
delegate = resp;
}
#Override
protected StringBuilder doInBackground(Void... params) {
try {
HttpURLConnection conn = null;
StringBuilder jsonResults = new StringBuilder();
String googleMapUrl = "http://maps.googleapis.com/maps/api/geocode/json?address=" + this.place + "&sensor=false";
URL url = new URL(googleMapUrl);
conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(
conn.getInputStream());
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
}
return jsonResults;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(StringBuilder result) {
super.onPostExecute(result);
try {
JSONObject jsonObj = new JSONObject(result.toString());
JSONArray resultJsonArray = jsonObj.getJSONArray("results");
JSONObject location = resultJsonArray
.getJSONObject(0).getJSONObject("geometry").getJSONObject("location");
String lat_helper = location.getString("lat");
double lat = Double.valueOf(lat_helper);
String lng_helper = location.getString("lng");
double lng = Double.valueOf(lng_helper);
delegate.processFinish(new LatLng(lat, lng));
} catch (JSONException e) {
e.printStackTrace();
}
}
}`

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;
}
}

Get data from execute action

there is any way that I can get the return data from execute action?
for example I have the next line that calls to the execute function - googlePlacesReadTask.execute(toPass); and the googlePlacesReadTask return some parser data to me. So how can I get this data that the action return to me ?
AsyncTask -
public class PlacesDisplayTask extends AsyncTask<Object, Integer, List<HashMap<String, String>>> {
JSONObject googlePlacesJson;
GoogleMap googleMap;
#Override
protected List<HashMap<String, String>> doInBackground(Object... inputObj) {
List<HashMap<String, String>> googlePlacesList = null;
Places placeJsonParser = new Places();
try {
googlePlacesJson = new JSONObject((String) inputObj[1]);
googlePlacesList = placeJsonParser.parse(googlePlacesJson);
} catch (Exception e) {
Log.d("Exception", e.toString());
}
if(String.valueOf(googlePlacesList) != "[]"){
//Find the place
}
else{
//No place found
}
return googlePlacesList;
}
}
second AsyncTask -
public class GooglePlacesReadTask extends AsyncTask<Object, Integer, String> {
String googlePlacesData = null;
GoogleMap googleMap;
#Override
protected String doInBackground(Object... inputObj) {
try {
googleMap = (GoogleMap) inputObj[0];
String googlePlacesUrl = (String) inputObj[1];
Http http = new Http();
googlePlacesData = http.read(googlePlacesUrl);
} catch (Exception e) {
Log.d("Google Place Read Task", e.toString());
}
return googlePlacesData;
}
#Override
protected void onPostExecute(String result) {
PlacesDisplayTask placesDisplayTask = new PlacesDisplayTask();
Object[] toPass = new Object[2];
toPass[0] = googleMap;
toPass[1] = result;
placesDisplayTask.execute(toPass);
}
}
Thanks.
Based on Which type of data you want to get from that method. If that method returns String data then save it in String variable.
For example :
In your case if googlePlacesReadTask returns String type of data then store it in string variable like :
String data = googlePlacesReadTask.execute(toPass);
Hope it will help
Use the onPostExecute method of your AsyncTask, there you have the response from the service (sent by the background process), handle it as you need.
If you need the data back in your class, you can send the AsyncTask a reference to it and call one class method from your AsyncTask sending it the required data
Just one way of doing it, there are more.
Dummy example:
public class MyAsyncTask extends AsyncTask<Void, Void, String> {
private MyClass myClass;
public MyAsyncTask(MyClass myClass) {
this.myClass = myClass;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(Void... params) {
return something;
}
#Override
protected void onPostExecute(String something) {
super.onPostExecute(something);
if(myClass != null){
myClass.thereYouGo(something);
}
}
}
From your class (MyClass):
new MyAsyncTask(this).execute();
Receiver method in MyClass:
public void thereYouGo(String something){
// do what you want
}

Hashmap size is not constant

I want to retrieve values from a Hash map. When i tried to display the size of a Hashmap in a TextView the size changes in my screen. Any ideas why?
Is there any other way instead of using Hashmap to store the JSONArray so it is more easy to retrieve values?
public void updateJSONdata() {
cafebartablesList = new ArrayList<HashMap<String, Integer>>();
JSONParser jParser = new JSONParser();
JSONObject json = jParser.getJSONFromUrl(READ_COMMENTS_URL);
try {
cafebartables = json.getJSONArray(TAG_POSTS);
for (int i = 0; i < cafebartables.length(); i++) {
LoadMap ld = new LoadMap();
ld.execute();
JSONObject c =cafebartables.getJSONObject(i);
int tableId = c.getInt(TAG_TABLE_ID);
int tableMarginLeft = c.getInt(TAG_MARGIN_LEFT);
int tableMarginTop = c.getInt(TAG_MARGIN_TOP);
int isFree = c.getInt(TAG_ISFREE);
map = new HashMap<String, Integer>();
map.put(TAG_TABLE_ID, tableId);
map.put(TAG_MARGIN_LEFT, tableMarginLeft);
map.put(TAG_MARGIN_TOP, tableMarginTop);
map.put(TAG_ISFREE, isFree);
cafebartablesList.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void printMap() {
mapcounter ++;
length_txt =(TextView)findViewById(R.id.length_txt);
length_txt.setText("the size is " +cafebartablesList.size());
}
public class LoadMap extends AsyncTask<Void, Void, Boolean> {
#Override
protected Boolean doInBackground(Void... arg0) {
updateJSONdata();
return null;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
printMap();
}
}
You're method is executing an asynctask that's recursively calling itself, which is probably causing some weird behavior.
Try something like this instead. have your print method call your asynctask. Your asynctask calls updateJSONdata, which iterates over the json object and constructs your map. At the end of your asynctask, update your textview with the size of your map.
public void updateJSONdata() {
cafebartablesList = new ArrayList<HashMap<String, Integer>>();
JSONParser jParser = new JSONParser();
JSONObject json = jParser.getJSONFromUrl(READ_COMMENTS_URL);
try {
cafebartables = json.getJSONArray(TAG_POSTS);
for (int i = 0; i < cafebartables.length(); i++) {
JSONObject c =cafebartables.getJSONObject(i);
int tableId = c.getInt(TAG_TABLE_ID);
int tableMarginLeft = c.getInt(TAG_MARGIN_LEFT);
int tableMarginTop = c.getInt(TAG_MARGIN_TOP);
int isFree = c.getInt(TAG_ISFREE);
map = new HashMap<String, Integer>();
map.put(TAG_TABLE_ID, tableId);
map.put(TAG_MARGIN_LEFT, tableMarginLeft);
map.put(TAG_MARGIN_TOP, tableMarginTop);
map.put(TAG_ISFREE, isFree);
cafebartablesList.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void printMap() {
LoadMap ld = new LoadMap();
ld.execute();
}
public class LoadMap extends AsyncTask<Void, Void, Boolean> {
#Override
protected Boolean doInBackground(Void... arg0) {
updateJSONdata();
return null;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
length_txt =(TextView)findViewById(R.id.length_txt);
length_txt.setText("the size is " +cafebartablesList.size());
}
}
}
Otherwise, you could use something like Gson, create a POJO for your cafebartablesList and call
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyPojo.class, new MyDeserializer())
.build();
MyPojo mp = gson.fromJson(json, MyPojo.class);

Iterate through a Hashmap and store values in variables for use

Hello I retrieved some data from a MySQL database and I stored this data in a Hashmap. I also have created a class which has the same variables as the Hashmap. I want to iterate through the Hashmap and store the values so I can use them for each object. Any ideas how to do it?
public void updateJSONdata() {
cafebartablesList = new ArrayList<HashMap<String, Integer>>();
JSONParser jParser = new JSONParser();
JSONObject json = jParser.getJSONFromUrl(READ_COMMENTS_URL);
try {
cafebartables = json.getJSONArray(TAG_POSTS);
for (int i = 0; i < cafebartables.length(); i++) {
JSONObject c =cafebartables.getJSONObject(i);
int tableId = c.getInt(TAG_TABLE_ID);
int tableMarginLeft = c.getInt(TAG_MARGIN_LEFT);
int tableMarginTop = c.getInt(TAG_MARGIN_TOP);
int isFree = c.getInt(TAG_ISFREE);
map = new HashMap<String, Integer>();
map.put(TAG_TABLE_ID, tableId);
map.put(TAG_MARGIN_LEFT, tableMarginLeft);
map.put(TAG_MARGIN_TOP, tableMarginTop);
map.put(TAG_ISFREE, isFree);
cafebartablesList.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void printMap() {
LoadMap ld = new LoadMap();
ld.execute();
}
public class LoadMap extends AsyncTask<Void, Void, Boolean> {
#Override
protected Boolean doInBackground(Void... arg0) {
updateJSONdata();
return null;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
}
}
}
Why do you want to do that? You're making your life difficult. There's a LinkedHashMap behind every JSONObject, so just use the JSONObject as is, without any conversion. I.e., use ArrayList<JSONObject> instead.

Categories

Resources