I created a new file for my AsyncTask, so I can break up my code into MVP.
File: TranslateAddress.java
public class TranslateAddress extends AsyncTask<String, Void, String> {
final Dialog customDialog = new Dialog(MainActivity.this);
protected void onPreExecute() {
super.onPreExecute();
customDialog.setContentView(R.layout.custom_location_dialog);
customDialog.setTitle("Looking for address");
TextView text = (TextView) customDialog.findViewById(R.id.textView);
text.setText("Looking for address");
customDialog.show();
}
protected String doInBackground(String... params) {
Geocoder geocoder;
List<Address> addresses = null;
geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
if (geocoder != null) {
try {
addresses = geocoder.getFromLocation(latitude, longitude, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5
} catch (IOException e) {
e.printStackTrace();
}
address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
city = addresses.get(0).getLocality();
state = addresses.get(0).getAdminArea();
country = addresses.get(0).getCountryName();
postalCode = addresses.get(0).getPostalCode();
knownName = addresses.get(0).getFeatureName(); // Only if available else return NULL
// do download here
} else {
Log.e("Error", "Geocoder returned Null");
MainActivity.OpenFragment("SolicitationFramgnet");
}
return null;
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
//dialog.dismiss();
customDialog.dismiss();
EditText localText = (EditText) findViewById(R.id.localText);
if (localText != null) {
localText.setText(address);
}
}
}
These are the lines that have errors:
final Dialog customDialog = new Dialog(MainActivity.this);
Error: MainActivity is not an enclosing class
geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
Error: Same as above, MainActivity is not an enclosing class
MainActivity.OpenFragment("SolicitationFramgnet");
Error: Non static method OpenFragment cannot be referenced from a static context. This error I can fix by making OpenFragment static, however, it breaks half of the code inside it.
EditText localText = (EditText) findViewById(R.id.localText);
Error: Cannot resolve method "findViewById(int)"
Moving your AsyncTask to another .java file you lose the reference of your MainActivity because before it functioned as an InnerClass and now it is just a Java Class, so you cannot use MainActivity methods or static context in this situation. Is the same thing for findViewById method because it belongs to your Activity and not to your AsyncTask. To fix it you have to pass the context in your Constructor and the main layout so you can use FindViewById method inside your TranslateAddress file using this View (as a parameter of your constructor).
Something like this:
public class TranslateAddress extends AsyncTask<String, Void, String> {
final Dialog customDialog;
private MainActivity mainActivity;
private View view;
public TranslateAddress(View view, MainActivity mainActivity){
this.view = view;
this.mainActivity = mainActivity;
}
protected void onPreExecute() {
super.onPreExecute();
customDialog = new Dialog(mainActivity);
customDialog.setContentView(R.layout.custom_location_dialog);
customDialog.setTitle("Looking for address");
TextView text = (TextView) customDialog.findViewById(R.id.textView);
text.setText("Looking for address");
customDialog.show();
}
protected String doInBackground(String... params) {
Geocoder geocoder;
List<Address> addresses = null;
geocoder = new Geocoder(mainActivity, Locale.getDefault());
if (geocoder != null) {
try {
addresses = geocoder.getFromLocation(latitude, longitude, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5
} catch (IOException e) {
e.printStackTrace();
}
address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
city = addresses.get(0).getLocality();
state = addresses.get(0).getAdminArea();
country = addresses.get(0).getCountryName();
postalCode = addresses.get(0).getPostalCode();
knownName = addresses.get(0).getFeatureName(); // Only if available else return NULL
// do download here
} else {
Log.e("Error", "Geocoder returned Null");
mainActivity.OpenFragment("SolicitationFramgnet");
}
return null;
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
//dialog.dismiss();
customDialog.dismiss();
EditText localText = (EditText) view.findViewById(R.id.localText);
if (localText != null) {
localText.setText(address);
}
}
}
For context, pass it from your MainActivity like this:
In AsyncTask, Create a constructor
Context context;
TranslateAddress(Context c){
context = c;
}
Now use context instead of MainActivity.this. And execute AsyncTask from MainActivity as following:
new TranslateAddress(this).execute();
and for findViewById(), use following code:
context.findViewById("YOUR_ID");
Related
I am following an Android weather app tutorial where the weather app requests a wether information about a place using an API;
However, the app was not "location aware" so I decided to try to do that, but when my app is created it calls the API with the hardcoded coordinates (private latitude and longitude). I dont understand why thid is happening, I am calling the getLoation method before the getForecast method. getLocation method should use the location manager's internet provider and set the latitude and longitude before the getForecast in called (which uses the coordinates to make the asynchronous API call). The strange thing is that when I press the refresh button, the location's coordinates are obtained from the location manager and the getLocationName is working fine too (finds the name of the location using the coordinates and set's the locationLabel to the name).
I suspect e problem is because if the fact that OkHTTP API that I am using to make the asynchronous call uses worker thread.
NODE: I am using Butter knife and YoYo API's also I have four classes which store the information about the weather called Forecast, Hour and Current and Day. I did not include them because I thought it is not important, since the problem is in my main activity class
Here is the code in my main activity class:
public static final String TAG = MainActivity.class.getSimpleName();
private Forecast mForecast;
//default coordinates - Aberdeen, UK Lati:57.156866 ; Long:
private double latitude = 57.156866;
private double longitude = -2.094278;
private LocationManager locationManager;
#InjectView(R.id.timeLabel) TextView mTimeLabel;
#InjectView(R.id.temperatureLabel) TextView mTemperatureLabel;
#InjectView(R.id.humidityValue) TextView mHumidityValue;
#InjectView(R.id.precipValue) TextView mPrecipValue;
#InjectView(R.id.summaryLabel) TextView mSummaryLabel;
#InjectView(R.id.locationLabel) TextView mLocationLabel;
#InjectView(R.id.windSpeedValue) TextView mWindSpeedValue;
#InjectView(R.id.iconImageView) ImageView mIconImageView;
#InjectView(R.id.refreshImageView) ImageView mRefreshImaveView;
#InjectView(R.id.progressBar) ProgressBar mProgressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
mProgressBar.setVisibility(View.INVISIBLE);
mRefreshImaveView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getLocation();
getForecast(latitude, longitude);
}
});
getLocation();
getForecast(latitude, longitude);
}
#Override
protected void onResume() {
super.onResume();
getForecast(latitude, longitude);
}
private void getForecast(double latitude, double longitude) {
//animations
YoYo.with(Techniques.FadeIn).duration(1800).playOn(mLocationLabel);
YoYo.with(Techniques.FadeIn).duration(1600).playOn(mTemperatureLabel);
YoYo.with(Techniques.FadeIn).duration(1800).playOn(mIconImageView);
YoYo.with(Techniques.FadeIn).duration(1000).playOn(mSummaryLabel);
YoYo.with(Techniques.FadeIn).duration(1200).playOn(mHumidityValue);
YoYo.with(Techniques.FadeIn).duration(1400).playOn(mWindSpeedValue);
YoYo.with(Techniques.FadeIn).duration(1200).playOn(mPrecipValue);
YoYo.with(Techniques.FadeIn).duration(1200).playOn(mTimeLabel);
String API_KEY = "API_KEY";
String forecast = "https://api.forecast.io/forecast/"+ API_KEY +"/"+ latitude+","+ longitude+"?units=auto";
if(isNetworkAvailable()) {
toggleRefresh();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecast)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
toggleRefresh();
}
});
alertUserAboutError();
}
//when the call to the Okhttp library finishes, than calls this method:
#Override
public void onResponse(Response response) throws IOException {
runOnUiThread(new Runnable() {
#Override
public void run() {
toggleRefresh();
}
});
try {
String jsonData = response.body().string();
//Log.v(TAG, jsonData);
if (response.isSuccessful()) {
mForecast = parseForecastDetails(jsonData);
runOnUiThread(new Runnable() {
#Override
public void run() {
updateDisplay();
}
});
} else {
alertUserAboutError();
}
} catch (IOException | JSONException e) {
Log.e(TAG, "Exception caught:", e);
}
}
});
}else{
//Toast.makeText(this,getString(R.string.network_unavailable_message),Toast.LENGTH_LONG).show();
WIFIDialogFragment dialog = new WIFIDialogFragment();
dialog.show(getFragmentManager(), getString(R.string.error_dialog_text));
}
}
private void toggleRefresh() {
if(mProgressBar.getVisibility() == View.INVISIBLE){
mProgressBar.setVisibility(View.VISIBLE);
mRefreshImaveView.setVisibility(View.INVISIBLE);
}else{
mProgressBar.setVisibility(View.INVISIBLE);
mRefreshImaveView.setVisibility(View.VISIBLE);
}
}
//updates the dysplay with the data in the CUrrentWeather locaal object
private void updateDisplay() {
Current current = mForecast.getCurrent();
//setting the current weather details to the ui
mTemperatureLabel.setText(current.getTemperature()+"");
mTimeLabel.setText("At "+ current.getFormattedTime()+" it will be");
mHumidityValue.setText(current.getHumidity() +"%");
mPrecipValue.setText(current.getPrecipChange()+"%");
mSummaryLabel.setText(current.getSummery());
mWindSpeedValue.setText(current.getWindSpeed()+"");
mLocationLabel.setText(current.getTimeZone());
//sets the mLocationLavel to the appropriate name and not the timezome from the API
getLocationName();
Drawable drawable = ContextCompat.getDrawable(this, current.getIconId());
mIconImageView.setImageDrawable(drawable);
}
private Forecast parseForecastDetails(String jsonData) throws JSONException {
Forecast forecast = new Forecast();
forecast.setCurrent(getCurrentDetails(jsonData));
forecast.setHourlyForecast(getHourlyForecast(jsonData));
forecast.setDailyForecast(getDailyForecast(jsonData));
return forecast;
}
private Day[] getDailyForecast(String jsonData) throws JSONException{
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
JSONObject daily = forecast.getJSONObject("daily");
JSONArray data = daily.getJSONArray("data");
Day[] days = new Day[data.length()];
for(int i = 0;i < data.length();i++){
JSONObject jsonDay = data.getJSONObject(i);
Day day = new Day();
day.setSummary(jsonDay.getString("summary"));
day.setIcon(jsonDay.getString("icon"));
day.setTemperatureMax(jsonDay.getDouble("temperatureMax"));
day.setTime(jsonDay.getLong("time"));
day.setTimezone(timezone);
days[i] = day;
Log.v(MainActivity.class.getSimpleName(),days[i].getIcon());
}
return days;
}
private Hour[] getHourlyForecast(String jsonData) throws JSONException{
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
JSONObject hourly = forecast.getJSONObject("hourly");
JSONArray data = hourly.getJSONArray("data");
Hour[]hours = new Hour[data.length()];
for(int i = 0;i < data.length();i++){
JSONObject jsonHour = data.getJSONObject(i);
Hour hour = new Hour();
hour.setSummary(jsonHour.getString("summary"));
hour.setTemperature(jsonHour.getDouble("temperature"));
hour.setIcon(jsonHour.getString("icon"));
hour.setTime(jsonHour.getLong("time"));
hour.setTimezone(timezone);
hours[i] = hour;
}
return hours;
}
/*
* throws JSONException, doing it like that, we place the
* responsability of handaling this exeption to the caller of the method
*/
private Current getCurrentDetails(String jsonData) throws JSONException{
JSONObject forecast = new JSONObject(jsonData);
String timezone = forecast.getString("timezone");
Log.i(TAG,"From JSON: " + timezone);
JSONObject currently = forecast.getJSONObject("currently");
Current mCurrent = new Current();
mCurrent.setHumidity(currently.getDouble("humidity"));
mCurrent.setTime(currently.getLong("time"));
mCurrent.setIcon(currently.getString("icon"));
mCurrent.setPrecipChange(currently.getDouble("precipProbability"));
mCurrent.setSummery(currently.getString("summary"));
mCurrent.setTemperature(currently.getDouble("temperature"));
mCurrent.setTimeZone(timezone);
mCurrent.setWindSpeed(currently.getDouble("windSpeed"));
Log.d(TAG, mCurrent.getFormattedTime());
return mCurrent;
}
private boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
//contition to check if there is a network and if the device is connected
if(networkInfo != null && networkInfo.isConnected()){
isAvailable = true;
}
return isAvailable;
}
private void alertUserAboutError() {
AlertDIalogFragment dialog = new AlertDIalogFragment();
dialog.show(getFragmentManager(),getString(R.string.error_dialog_text));
}
private void getLocation(){
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if(isNetworkAvailable()){
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 1, 1000, new MyLocationListener());
}else{
WIFIDialogFragment dialog = new WIFIDialogFragment();
dialog.show(getFragmentManager(), getString(R.string.error_dialog_text));
}
}
private class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
latitude = loc.getLatitude();
longitude = loc.getLongitude();
Toast.makeText(MainActivity.this,
"Location changed: Lat: " + loc.getLatitude() + " Lng: "
+ loc.getLongitude(), Toast.LENGTH_SHORT).show();
locationManager.removeUpdates(this);
}
#Override
public void onProviderDisabled(String provider) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
private void getLocationName(){
Geocoder geo = new Geocoder(this, Locale.getDefault());
try {
List<Address> addressList = geo.getFromLocation(this.latitude,this.longitude,1);
if (addressList.isEmpty()){
//gets the default name from the timeZone
//that we set in as a local variable
}else{
if(addressList.size() > 0){
Log.v(MainActivity.class.getSimpleName(),addressList.get(0).getLocality() + ", "+ addressList.get(0).getCountryName()+"");
mLocationLabel.setText(addressList.get(0).getLocality() + ", "+ addressList.get(0).getCountryName());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
This is a screenshot of the app:
By looking at your code, there are couple of things which are wrong.
you have called getLocation Method in OnCreate and onResume as well which is logically incorrect. you can keep it at onResume only if you wish you get location frequently.
when we call getLocation method it's not guarantee to give the latitude and longitude straight away, it takes it's own sweet time depending on the providers (Read API of location manager) hence your first call for getForecast will probably fail.
Solution : you can call getForecast method when onLocationChange method is called, by that time you can show progressDialog.
Make sure you have given Location related permissions in the manifest file
I am developing an android application which displays a map. When it loads, it displays some addresses and sets markers for them.
When I click on any marker it should display a value in a custom view. But the custom text which is received from a json parser, gets a null value. When I click on the marker again, it sets correct value.
When I click on second marker it display 1st marker value. When I click on 2nd marker again it displays correct value. This process continues
Here's my code:
private class GeocoderTask extends AsyncTask<String, Void, List<Address>>{
private Context mainContxt;
Geocoder geocoder;
public GeocoderTask(Context con){
mainContxt=con;
}
#Override
protected List<Address> doInBackground(String... locationName) {
Geocoder geocoder = new Geocoder(mainContxt);
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocationName(locationName[0],1);
} catch (IOException e) {
e.printStackTrace();
}
return addresses;
}
#Override
protected void onPostExecute(List<Address> addresses) {
for(int i=0;i<addresses.size();i++){
Address address = (Address) addresses.get(i);
latLng = new LatLng(address.getLatitude(), address.getLongitude());
String addressText = String.format("%s, %s",
address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "",
address.getCountryName());
markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(addressText);
if(i==0) {
googleMap.animateCamera(CameraUpdateFactory.zoomBy(14),2000,null);
googleMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
}
googleMap.addMarker(markerOptions);
}
googleMap.setOnMarkerClickListener(new OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker_address) {
location=marker_address.getTitle();
Toast.makeText(getApplicationContext(),location, Toast.LENGTH_LONG).show();
new LoadSingleProperty().execute();
//new LoadImage().execute();
return false;
}
});
googleMap.setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
View myContentView = getLayoutInflater().inflate(
R.layout.custom_marker, null);
tempnew_price=getPrice(temptotal_price+"" +email);
TextView tvTitle = ((TextView) myContentView
.findViewById(R.id.title));
// tvTitle.setText(location);
tvSnippet = ((TextView) myContentView
.findViewById(R.id.snippet));
ivProperty = ((ImageView) myContentView
.findViewById(R.id.image_property));
tvTitle.setText(tempcovered_area+ " "+tempnew_price+System.getProperty("line.separator")+templocation);
tvSnippet.setText("A "+ tempbedroom + " "+tempproperty_type);
// new LoadImage().execute();
ivProperty.setImageBitmap(bmp);
return myContentView;
}
});
googleMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker arg0) {
Intent intent = new Intent(getBaseContext(),
search_property_activity.class);
intent.putExtra("Email", email);
startActivity(intent);
}
});
}
}
this is my loadsingle class coding.....
class LoadSingleProperty extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivityMap.this);
pDialog.setMessage("Loading Location. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected String doInBackground(String... args) {
List<NameValuePair> params = new ArrayList<NameValuePair>();
if(location!=null && !location.equals("")){
params.add(new BasicNameValuePair("Location", location));
json= jsonParser.makeHttpRequest(url_loc_address, "GET", params);
}
Log.d("MyLocation: ", json.toString());
try {
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
address = json.getJSONArray(TAG_ALL_ADDRESS);
//for (int i = 0; i < address.length(); i++) {
JSONObject c = address.getJSONObject(0);
templocation = c.getString(TAG_LOCATION);
tempcovered_area=c.getString(TAG_COVERED_AREA);
temptotal_price=c.getString(TAG_Total_Price);
tempbedroom=c.getString(TAG_BEDROOM);
tempproperty_type=c.getString(TAG_PROPERTY_TYPE);
tempemail=c.getString(TAG_EMAIL);
//}
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String file_url) {
pDialog.dismiss();
new GeocoderTask(MainActivityMap.this).execute(location);
}
}
Help me friends ...thx in advance
Create a constructor for LoadSingleProperty
class LoadSingleProperty extends AsyncTask<String, String, String> {
Marker mMarker;
public LoadSingleProperty(Marker marker){
mMarker = marker;
}
.
.
.
}
and pass your marker object to it.
new LoadSingleProperty(marker_address).execute();
Once parsing is done set your marker's title using setTitle() method for the marker
mMarker.setTitle(c.getString(TAG_PROPERTY_TYPE));
where you currently do this
tempproperty_type=c.getString(TAG_PROPERTY_TYPE);
Don't forget to refresh your info window once title is reset
How to force refresh contents of the markerInfoWindow
You may also want to show some sort of a loading icon till this time since you're performing a network request.
EDIT:
In case you're using a custom titleview, get a reference to InfoWindowAdapter object before setting as a adapter to googleMap
InfoWindowAdapter infoWindowAdapter = new InfoWindowAdapter() {...
Once parsing is complete, get info window view for mMarker object by calling
infoWindowAdapter.getInfoWindow(mMarker);
Find your textView from the view obtained above and set its text. Then refresh your info window by calling showInfoWindow() to update the info window.
Also please refer this link.
The info window that is drawn is not a live view. The view is rendered
as an image (using View.draw(Canvas)) at the time it is returned. This
means that any subsequent changes to the view will not be reflected by
the info window on the map. To update the info window later (for
example, after an image has loaded), call showInfoWindow()
private class GeocoderTask extends AsyncTask<String, Void, List<Address>> {
private Context mainContxt;
Geocoder geocoder;
public GeocoderTask(Context con) {
mainContxt = con;
}
#Override
protected List<Address> doInBackground(String... locationName) {
Geocoder geocoder = new Geocoder(mainContxt);
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocationName(locationName[0], 1);
} catch (IOException e) {
e.printStackTrace();
}
return addresses;
}
#Override
protected void onPostExecute(List<Address> addresses) {
for (int i = 0; i < addresses.size(); i++) {
Address address = (Address) addresses.get(i);
latLng = new LatLng(address.getLatitude(),
address.getLongitude());
String addressText = String.format(
"%s, %s",
address.getMaxAddressLineIndex() > 0 ? address
.getAddressLine(0) : "", address
.getCountryName());
markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(addressText);
if (i == 0) {
googleMap.animateCamera(CameraUpdateFactory.zoomBy(14),
2000, null);
googleMap.animateCamera(CameraUpdateFactory
.newLatLng(latLng));
}
googleMap.addMarker(markerOptions);
}
}
}
Then you write below code
googleMap.setOnMarkerClickListener(new OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker_address) {
location = marker_address.getTitle();
new LoadSingleProperty().execute();
return false;
}
});
Take another customeWindowAdapter or else use the present one only and set that in onPostExecute() method of 'LoadSingleProperty' AsyncTask..
This will solve that.
ping here you have any queries
I tried to use reverse geocoding with AsyncTask but but the parameters of latitude and longitude that passes through the method doInBackground() are not happening correctly. any idea?
public class SitesAdapter extends ArrayAdapter<StackSite> {
public static Double lat;
public static Double lng;
#Override
public View getView(int pos, View convertView, ViewGroup parent){
...
lat = -1.80;
lng = -80.20;
...
}
public void start(){
new GetAddressTask(mContext).execute(lat, lng);
}
public static class GetAddressTask extends AsyncTask<Double, Void, String> {
//mContext
#Override
protected String doInBackground(Double... params) {
Geocoder gc = new Geocoder(mContext, Locale.getDefault());
List<Address> list = null;
String city = "";
double latitude = params[0];
double longitude = params[1];
try {
list = gc.getFromLocation(lat, lng, 1);
} catch (IOException e) {
e.printStackTrace();
}
if (list != null && list.size() > 0) {
Address address = list.get(0);
city = String.format("%s, %s", address.getAdminArea(), address.getCountryName());
}
return city;
}
#Override
protected void onPostExecute(String city) {
tituloTxt.setText(city);
}
}
}
error:
11-21 15:10:24.409: E/Trace(24502): error opening trace file: No such file or directory (2)
Well after so only had to do this to pass the coordinates. First add coordinate to constructor LatLng(double latitude, double longitude) and pass the parameters.
lat = -1.80;
lng = -80.20;
LatLng latlng = new LatLng(lat, lng);
new GetAddressTask(mContext).execute(lat, lng);
Then inside the doInbackground method get parameters.
public static class GetAddressTask extends AsyncTask<LatLng, Void, String> {
//mContext
#Override
protected String doInBackground(LatLng... params) {
Geocoder gc = new Geocoder(mContext, Locale.getDefault());
List<Address> list = null;
String city = "";
LatLng loc = params[0]; //Get all parameters: latitude and longitude
try {
list = gc.getFromLocation(loc.latitude, loc.longitude, 1); //get specific parameters
} catch (IOException e) {
e.printStackTrace();
}
if (list != null && list.size() > 0) {
Address address = list.get(0);
city = String.format("%s, %s", address.getAdminArea(), address.getCountryName());
return city;
}else{
return "City no found";
}
}
#Override
protected void onPostExecute(String city) {
tituloTxt.setText(city);
}
}
before calling execute method, u can just create a constructor ,in which you can initialize your class data members which can be further used in doInBackground(..).
Add two variables to your class and set them when you create async task, then use them in method. Simple.
public class GetAddressTask extends AsyncTask<String, Void, String> {
Context mContext;
float lat,lin;
public void setLat(int lat){...}
//rest of class
of course you can make everything static (fields and setters).
Edit.
If you are calling execute with some parameters, remember that your values have to be set before calling execute.
Code 1 is a part of my Fragment class
From Code 1 i am getting my place name. I want to pass that place name to a non Activity class That is to CODE 2.
Code 1
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
gps = new GPSTracker(getActivity());
Geocoder geocoder= new Geocoder(getActivity(), Locale.ENGLISH);
myAddress=(TextView)getView().findViewById(R.id.gpsLocation);
surveyView = (SurveyView) getView().findViewById(R.id.surveyView);
newsHomeView = (NewsHomeView) getView().findViewById(R.id.newsHomeView);
audioView = (AudioItemView) getView().findViewById(R.id.audioView);
AudioListener listener = (AudioListener)getActivity();
audioView.setListener(listener);
newsHomeView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity mnAct = (MainActivity)HomeFragment.this.getActivity();
mnAct.moveToPage(Constants.NEWS_PAGE);
}
});
iPrevIndex = -1;
// check if GPS enabled
if(gps.canGetLocation()){
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
// \n is for new line
//Toast.makeText(getApplicationContext(), "Your Location is - \nLat: " + latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
try {
//Place your latitude and longitude
// List<Address> addresses = geocoder.getFromLocation(37.423247,-122.085469, 1);
List<Address> addresses = geocoder.getFromLocation(latitude,longitude, 1);
if(addresses != null) {
Address fetchedAddress = addresses.get(0);
StringBuilder strAddress = new StringBuilder();
for(int i=0; i<=fetchedAddress.getMaxAddressLineIndex(); i++) {
strAddress.append(fetchedAddress.getAddressLine(i)).append("\n");
}
Log.i("country name ",fetchedAddress.getAddressLine(fetchedAddress.getMaxAddressLineIndex()));
String s=fetchedAddress.getAddressLine(fetchedAddress.getMaxAddressLineIndex()-1);// Bangalore, Karnataka, 560038
String str[]=s.split(" ");// array of Bangalore, Karnataka, 560038
System.out.println(Arrays.toString(str)); // print all array element
// myAddress.setText("You'r location is: " +strAddress.toString());
}
else
myAddress.setText("No location found..!");
// Toast.makeText(getActivity(),"Please switch on yor gps",Toast.LENGTH_LONG).show();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(getActivity(),"Could not get address..!", Toast.LENGTH_LONG).show();
}
}else{
// can't get location
// GPS or Network is not enabled
// Ask user to enable GPS/network in settings
gps.showSettingsAlert();
}
}
CODE 2
public class Audios extends BaseCollection<Audio> {
private static String newValue;
public static setNewValue(String value) {
this.newValue = value;
//Code to use this value.
}
#Override
public void loadWithJson(JSONArray jsonObj) {
if(null == jsonObj) {
return;
}
try {
List<Audio> entries = new ArrayList<Audio>();
for (int o = 0; o < jsonObj.length(); ++o) {
Audio opt = Audio.fromJson(jsonObj.getJSONObject(o));
// String title = opt.getTitle();
//System.out.println(opt.getTitle().substring(0, 4)); // title.substring(0, 3);
// entries.add(opt);
entries.add(opt);
}
this.entries = entries;
} catch (Exception e) {
e.printStackTrace();
}
}
public void getAudioResult(JSONObject jsonRes) {
int id, grpId, dwnCount, upCount;
if(null != jsonRes) {
try {
id = jsonRes.getInt(Constants.MEDIA_ID);
grpId = jsonRes.getInt(Constants.GROUP_ID);
dwnCount= jsonRes.getInt(Constants.SET_THUMBS_DWN);
upCount = jsonRes.getInt(Constants.SET_THUMBS_UP);
}
catch(JSONException je) { id = grpId = dwnCount = upCount = -1;}
if(-1 == id || -1 == grpId) {
return;
}
for(int iLoop = 0; iLoop < entries.size(); iLoop++) {
Audio opt = entries.get(iLoop);
if(opt.token == id && opt.groupId == grpId) {
opt.thumbDwns = dwnCount;
opt.thumbUps = upCount;
break;
}
}
}
}
}
In code 1 Hear i am getting my place name
Values:
place=str[1].substring(0, 4);
AudiosFragment hm=new AudiosFragment();
Bundle bundle = new Bundle();
bundle.putString("place", str[1].substring(0, 4));
Please tell me how i will pass this place value.
easy way to pass data from one class to another is by using constructor
Consider Example:
Class A{
Object o;
private methodA()
{
B b = new B(o); //here you are passing o to Class B
b.methodB();
}
}
Class B{
Object o;
public B(Object O)
{
this.o=o;
}
public methodB()
{
use object o here
}
}
may be this will help..
You can use a Singleton class but is maybe to complex for only a String [].
public class Singleton {
private static Singleton uniqInstance;
private String str[];
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (uInstance == null) {
uInstance = new Singleton();
}
return uInstance;
}
}
Just create a method inside the Audios Class.
Now, depending on the fact that you want different objects of the Audio Class to have different value for this String, you can define it static or not. Then just call that method.
Example :
Class Audios extends BaseCollection<Audio> {
private static String newValue;
public static void setNewValue(String value) {
this.newValue = value;
//Code to use this value.
..
}
}
From the Fragment, just call Audios.setNewValue("This is the value for the String");
I'd like to set a ListView to data I get from a web service. I get the data in a AsyncTask instance, but when I try to set some of my ListView attributes, it crashes (on line "lv.setVisibility(View.VISIBLE);"). Anybody can help?
thanks
public class Atable extends Activity {
private EditText mSearch;
private static final int ACTIVITY_EDIT=0;
private Button mSearchButton;
private TextView mNoresults;
private ListView lv;
private CheckBox checkBox;
private LocationManager locationManager;
private RestaurantList restaurantList;
private Criteria criteria;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv= (ListView)findViewById(R.id.listview);
mNoresults = (TextView) findViewById(R.id.noresults);
mNoresults.setVisibility(View.GONE);
mSearchButton = (Button)this.findViewById(R.id.button);
checkBox = (CheckBox) findViewById(R.id.local_check);
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
mSearchButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mNoresults.setVisibility(View.GONE);
mSearch = (EditText) findViewById(R.id.search);
String tmp_str = mSearch.getText().toString().replace(" ","+");
String url = "http://www.atable.org/getRestaurantByQuery/?query=" + tmp_str;
if (checkBox.isChecked()) {
//get location
String provider = locationManager.getBestProvider(criteria, true);
Location location = locationManager.getLastKnownLocation(provider);
if (location!=null) {
String lat = String.valueOf(location.getLatitude());
String lng = String.valueOf(location.getLongitude());
url += "&lat="+lat+"&lng="+lng;
}
}
new GetRestaurantData().execute(url);
}
});
};
private class GetRestaurantData extends AsyncTask<String, Boolean, RestaurantList> {
private HttpClient httpclient = new DefaultHttpClient();
#Override
protected RestaurantList doInBackground(String... url) {
publishProgress(true);
HttpGet httpget = new HttpGet(url[0]);
// Execute the request
HttpResponse response;
try {
response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
Reader r = new InputStreamReader(instream);
Gson gson = new Gson();
restaurantList = gson.fromJson(r, RestaurantList.class);
int nResults = restaurantList.getSize();
if (nResults>0) {
lv.setVisibility(View.VISIBLE); //app crashes here
lv.setAdapter( new ArrayAdapter<String>(Atable.this ,android.R.layout.simple_list_item_1,restaurantList.getRestaurantNames()));
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(Atable.this, RestaurantDescription.class);
Restaurant tmp_resto = restaurantList.getRestaurant((int)id);
String tmp_categories = tmp_resto.getCategories().get(0);
for (int i=1; i<tmp_resto.getCategories().size(); i++) {
tmp_categories+=", "+tmp_resto.getCategories().get(i);
}
String address = tmp_resto.getStreet()+", "+tmp_resto.getStreetNumber()+"\n"+tmp_resto.getCity()+
" "+tmp_resto.getPostalCode()+"\n"+tmp_resto.getCountry();
intent.putExtra("name", tmp_resto.getName());
intent.putExtra("address", address);
intent.putExtra("rating", tmp_resto.getRating());
intent.putExtra("price_range", tmp_resto.getPriceRange());
intent.putExtra("categories", tmp_categories);
intent.putExtra("latitude", tmp_resto.getLatitude());
intent.putExtra("longitude", tmp_resto.getLongitude());
startActivityForResult(intent, ACTIVITY_EDIT);
}
});
}
else {
lv.setVisibility(View.GONE);
mNoresults.setVisibility(View.VISIBLE);
}
//Closing the input stream will trigger connection release
instream.close();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return restaurantList;
}
#Override
protected void onProgressUpdate(Boolean... progress) {
// line below coupled with
// getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS)
// before setContentView
// will show the wait animation on the top-right corner
Atable.this.setProgressBarIndeterminateVisibility(progress[0]);
}
#Override
protected void onPostExecute(RestaurantList result) {
publishProgress(false);
// Do something with result in your activity
}
}
In Android, all UI updates are done on the main thread (also called UI thread). It's good when you spawn a new thread to do time consuming tasks in order not to block the UI.
But in order to avoid all sorts of indeterminate behaviors, UI updates always have to be done on the UI thread. If you ever attempt to do so from a different thread, an exception will be thrown.
In your example, I see you're performing different updatings to ListView based on the value of nResults. You can try returning nResults for doInBackground(). It will be passed to onPostExecute(), which will be executed on the UI thread.
You wanna check out this article for some useful information about threadings in Android: http://android-developers.blogspot.com/2009/05/painless-threading.html
HTH
You can't access the ui thread from the doinbachground method.. you need to do that from the post execute, pre execute or on progress update methods...