From: gu.martinm@gmail.com Date: Wed, 2 Apr 2014 03:33:00 +0000 (+0200) Subject: No time for comments X-Git-Tag: weatherinformation-1.0~193 X-Git-Url: https://git.gumartinm.name/?a=commitdiff_plain;h=12ab5412233728baf7124fcf83abc5720b8b4769;p=AndroidWeatherInformation No time for comments --- diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a0f5d7b..8ae62c1 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -15,11 +15,11 @@ @@ -29,9 +29,8 @@ + android:parentActivityName="de.example.exampletdd.WeatherInformationActivity"> diff --git a/res/drawable-hdpi/ic_action_search.png b/res/drawable-hdpi/ic_action_search.png new file mode 100644 index 0000000..772e359 Binary files /dev/null and b/res/drawable-hdpi/ic_action_search.png differ diff --git a/res/drawable-mdpi/ic_action_search.png b/res/drawable-mdpi/ic_action_search.png new file mode 100644 index 0000000..4edb1ff Binary files /dev/null and b/res/drawable-mdpi/ic_action_search.png differ diff --git a/res/drawable-xhdpi/ic_action_search.png b/res/drawable-xhdpi/ic_action_search.png new file mode 100644 index 0000000..19658e4 Binary files /dev/null and b/res/drawable-xhdpi/ic_action_search.png differ diff --git a/res/drawable-xxhdpi/ic_action_search.png b/res/drawable-xxhdpi/ic_action_search.png new file mode 100644 index 0000000..a108638 Binary files /dev/null and b/res/drawable-xxhdpi/ic_action_search.png differ diff --git a/res/layout/activity_main.xml b/res/layout/activity_main.xml index e872532..c3dbbfd 100644 --- a/res/layout/activity_main.xml +++ b/res/layout/activity_main.xml @@ -11,6 +11,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" class="de.example.exampletdd.fragment.WeatherInformationDataFragment" - tools:layout="@layout/fragment_main" /> + tools:layout="@layout/weather_data_list" /> diff --git a/res/layout/weather_data_entry_list.xml b/res/layout/weather_data_entry_list.xml new file mode 100644 index 0000000..0f3cb7c --- /dev/null +++ b/res/layout/weather_data_entry_list.xml @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/res/layout/weather_data_list.xml b/res/layout/weather_data_list.xml new file mode 100644 index 0000000..e10ceb3 --- /dev/null +++ b/res/layout/weather_data_list.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/res/menu/weather_main_menu.xml b/res/menu/weather_main_menu.xml index 72e7142..30460b2 100644 --- a/res/menu/weather_main_menu.xml +++ b/res/menu/weather_main_menu.xml @@ -1,5 +1,6 @@ + + android:showAsAction="never"> + diff --git a/res/values/strings.xml b/res/values/strings.xml index 5445332..d0c9b0c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3,6 +3,7 @@ Weather Information Settings + City,country Get weather http://api.openweathermap.org/data/{0}/weather?lat={1}&lon={2} http://api.openweathermap.org/data/{0}/weather?q={1} @@ -12,12 +13,17 @@ City name Latitude Longitude - Sun rise time - Sun set time - Weather description - Temperature - Min temperature - Max temperature + Sun rise time: + Sun set time: + Weather description: + Temperature: + Min temperature: + Max temperature: + Cloudiness: + Rain time: + Rain amount: + Wind speed: + Humidity in %: OK Connection error timeout Impossible to receive weather data. diff --git a/src/de/example/exampletdd/WeatherInformationActivity.java b/src/de/example/exampletdd/WeatherInformationActivity.java index e3c53c4..ae260ee 100644 --- a/src/de/example/exampletdd/WeatherInformationActivity.java +++ b/src/de/example/exampletdd/WeatherInformationActivity.java @@ -23,14 +23,14 @@ public class WeatherInformationActivity extends Activity implements ErrorMessage super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_main); - PreferenceManager.setDefaultValues(this, R.xml.weather_preferences, - false); + PreferenceManager.setDefaultValues(this, R.xml.weather_preferences, false); final ActionBar actionBar = this.getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE); - actionBar.setTitle(this.getResources().getString(R.string.header_action_bar)); + actionBar.setDisplayOptions(ActionBar.DISPLAY_USE_LOGO, ActionBar.DISPLAY_USE_LOGO); + // actionBar.setTitle(this.getResources().getString(R.string.header_action_bar)); + actionBar.setDisplayHomeAsUpEnabled(true); // Better using xml files? How to deal with savedInstanceState with xml files? // final WeatherDataFragment weatherDataFragment = new WeatherDataFragment(); diff --git a/src/de/example/exampletdd/fragment/WeatherDataAdapter.java b/src/de/example/exampletdd/fragment/WeatherDataAdapter.java new file mode 100644 index 0000000..71d6cb2 --- /dev/null +++ b/src/de/example/exampletdd/fragment/WeatherDataAdapter.java @@ -0,0 +1,91 @@ +package de.example.exampletdd.fragment; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; +import de.example.exampletdd.R; + +public class WeatherDataAdapter extends ArrayAdapter { + private final int resource; + + public WeatherDataAdapter(final Context context, final int resource) { + super(context, 0); + + this.resource = resource; + } + + @Override + public View getView(final int position, final View convertView, + final ViewGroup parent) { + + // We need to get the best view (re-used if possible) and then + // retrieve its corresponding ViewHolder, which optimizes lookup + // efficiency + final View view = this.getWorkingView(convertView); + final ViewHolder viewHolder = this.getViewHolder(view); + final WeatherDataEntry entry = this.getItem(position); + + + // Setting the text view + viewHolder.headerView.setText(entry.getHeader()); + viewHolder.bodyView.setText(entry.getBody()); + + + return view; + } + + private View getWorkingView(final View convertView) { + // The workingView is basically just the convertView re-used if possible + // or inflated new if not possible + View workingView = null; + + if(null == convertView) { + final Context context = this.getContext(); + final LayoutInflater inflater = (LayoutInflater)context.getSystemService + (Context.LAYOUT_INFLATER_SERVICE); + + workingView = inflater.inflate(this.resource, null); + } else { + workingView = convertView; + } + + return workingView; + } + + private ViewHolder getViewHolder(final View workingView) { + // The viewHolder allows us to avoid re-looking up view references + // Since views are recycled, these references will never change + final Object tag = workingView.getTag(); + ViewHolder viewHolder = null; + + + if((null == tag) || !(tag instanceof ViewHolder)) { + viewHolder = new ViewHolder(); + + viewHolder.headerView = (TextView) workingView + .findViewById(R.id.weather_data_entry_header); + viewHolder.bodyView = (TextView) workingView + .findViewById(R.id.weather_data_entry_body); + + workingView.setTag(viewHolder); + + } else { + viewHolder = (ViewHolder) tag; + } + + return viewHolder; + } + + /** + * ViewHolder allows us to avoid re-looking up view references + * Since views are recycled, these references will never change + */ + private static class ViewHolder { + public TextView headerView; + public TextView bodyView; + } + +} diff --git a/src/de/example/exampletdd/fragment/WeatherDataEntry.java b/src/de/example/exampletdd/fragment/WeatherDataEntry.java new file mode 100644 index 0000000..45dd979 --- /dev/null +++ b/src/de/example/exampletdd/fragment/WeatherDataEntry.java @@ -0,0 +1,20 @@ +package de.example.exampletdd.fragment; + +public class WeatherDataEntry { + private final String header; + private final String body; + + public WeatherDataEntry(final String header, final String body) { + this.header = header; + this.body = body; + } + + public String getHeader() { + return this.header; + } + + public String getBody() { + return this.body; + } + +} diff --git a/src/de/example/exampletdd/fragment/WeatherInformationDataFragment.java b/src/de/example/exampletdd/fragment/WeatherInformationDataFragment.java index 9e47ce1..0dcf6db 100644 --- a/src/de/example/exampletdd/fragment/WeatherInformationDataFragment.java +++ b/src/de/example/exampletdd/fragment/WeatherInformationDataFragment.java @@ -6,15 +6,14 @@ import java.net.URISyntaxException; import java.net.URL; import java.text.DecimalFormat; import java.text.SimpleDateFormat; -import java.util.Date; +import java.util.ArrayList; +import java.util.Collection; import org.apache.http.client.ClientProtocolException; import org.json.JSONException; import android.app.Fragment; import android.content.SharedPreferences; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.net.http.AndroidHttpClient; import android.os.AsyncTask; import android.os.Bundle; @@ -23,8 +22,7 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.EditText; -import android.widget.ImageView; +import android.widget.ListView; import de.example.exampletdd.R; import de.example.exampletdd.activityinterface.ErrorMessage; import de.example.exampletdd.activityinterface.OnClickButtons; @@ -35,35 +33,47 @@ import de.example.exampletdd.parser.JPOSWeatherParser; import de.example.exampletdd.service.WeatherService; public class WeatherInformationDataFragment extends Fragment implements OnClickButtons { + private WeatherDataAdapter mAdapter; private boolean isFahrenheit; - private EditText weatherDescription; - private EditText temperature; - private EditText maxTemperature; - private EditText minTemperature; - private EditText sunRise; - private EditText sunSet; - private ImageView imageIcon; @Override public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { - final View rootView = inflater.inflate(R.layout.fragment_main, + final View rootView = inflater.inflate(R.layout.weather_data_list, container, false); - - this.weatherDescription = (EditText) rootView.findViewById(R.id.editTextWeatherDescription); - this.temperature = (EditText) rootView.findViewById(R.id.editTextTemperature); - this.maxTemperature = (EditText) rootView.findViewById(R.id.editTextMaxTemperature); - this.minTemperature = (EditText) rootView.findViewById(R.id.editTextMinTemperature); - this.sunRise = (EditText) rootView.findViewById(R.id.editTextSunRise); - this.sunSet = (EditText) rootView.findViewById(R.id.editTextSunSet); - this.imageIcon = (ImageView) rootView.findViewById(R.id.imageIcon); - return rootView; } @Override + public void onActivityCreated(final Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + final ListView listWeatherView = (ListView) this.getActivity().findViewById( + R.id.weather_data_list_view); + + this.mAdapter = new WeatherDataAdapter(this.getActivity(), + R.layout.weather_data_entry_list); + + final Collection entries = new ArrayList(); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_description), "")); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_tem), "")); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_tem_max), "")); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_tem_min), "")); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_sun_rise), "")); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_sun_set), "")); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_cloudiness), "")); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_rain_time), "")); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_rain_amount), "")); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_wind_speed), "")); + entries.add(new WeatherDataEntry(this.getString(R.string.text_field_humidity), "")); + + this.mAdapter.addAll(entries); + listWeatherView.setAdapter(this.mAdapter); + } + + @Override public void onClickGetWeather(final View v) { final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser(); @@ -76,10 +86,8 @@ public class WeatherInformationDataFragment extends Fragment implements OnClickB final WeatherTask weatherTask = new WeatherTask(HTTPweatherClient, weatherService); - final EditText cityCountry = (EditText) this.getActivity() - .findViewById(R.id.editTextCity); - weatherTask.execute(cityCountry.getText().toString()); + weatherTask.execute("London,uk"); } public void updateWeatherData(final WeatherData weatherData) { @@ -88,36 +96,15 @@ public class WeatherInformationDataFragment extends Fragment implements OnClickB final double tempUnits = this.isFahrenheit ? 0 : 273.15; if (weatherData.getWeather() != null) { - this.weatherDescription.setText(weatherData.getWeather() - .getDescription()); - double conversion = weatherData.getMain().getTemp(); - conversion = conversion - tempUnits; - this.temperature.setText(tempFormatter.format(conversion)); - conversion = weatherData.getMain().getMaxTemp(); - conversion = conversion - tempUnits; - this.maxTemperature.setText(tempFormatter.format(conversion)); - conversion = weatherData.getMain().getMinTemp(); - conversion = conversion - tempUnits; - this.minTemperature.setText(tempFormatter.format(conversion)); + } if (weatherData.getSystem() != null) { - long unixTime = weatherData.getSystem().getSunRiseTime(); - Date unixDate = new Date(unixTime * 1000L); - String dateFormatUnix = dateFormat.format(unixDate); - this.sunRise.setText(dateFormatUnix); - - unixTime = weatherData.getSystem().getSunSetTime(); - unixDate = new Date(unixTime * 1000L); - dateFormatUnix = dateFormat.format(unixDate); - this.sunSet.setText(dateFormatUnix); + } if (weatherData.getIconData() != null) { - final Bitmap icon = BitmapFactory.decodeByteArray( - weatherData.getIconData(), 0, - weatherData.getIconData().length); - this.imageIcon.setImageBitmap(icon); + } } diff --git a/src/de/example/exampletdd/fragment/WeatherInformationDataFragmentDeprecated.java b/src/de/example/exampletdd/fragment/WeatherInformationDataFragmentDeprecated.java new file mode 100644 index 0000000..939ec12 --- /dev/null +++ b/src/de/example/exampletdd/fragment/WeatherInformationDataFragmentDeprecated.java @@ -0,0 +1,228 @@ +package de.example.exampletdd.fragment; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.http.client.ClientProtocolException; +import org.json.JSONException; + +import android.app.Fragment; +import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.http.AndroidHttpClient; +import android.os.AsyncTask; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.ImageView; +import de.example.exampletdd.R; +import de.example.exampletdd.activityinterface.ErrorMessage; +import de.example.exampletdd.activityinterface.OnClickButtons; +import de.example.exampletdd.httpclient.WeatherHTTPClient; +import de.example.exampletdd.model.WeatherData; +import de.example.exampletdd.parser.IJPOSWeatherParser; +import de.example.exampletdd.parser.JPOSWeatherParser; +import de.example.exampletdd.service.WeatherService; + +public class WeatherInformationDataFragmentDeprecated extends Fragment implements OnClickButtons { + private boolean isFahrenheit; + private EditText weatherDescription; + private EditText temperature; + private EditText maxTemperature; + private EditText minTemperature; + private EditText sunRise; + private EditText sunSet; + private ImageView imageIcon; + + + @Override + public View onCreateView(final LayoutInflater inflater, + final ViewGroup container, final Bundle savedInstanceState) { + final View rootView = inflater.inflate(R.layout.fragment_main, + container, false); + + + this.weatherDescription = (EditText) rootView.findViewById(R.id.editTextWeatherDescription); + this.temperature = (EditText) rootView.findViewById(R.id.editTextTemperature); + this.maxTemperature = (EditText) rootView.findViewById(R.id.editTextMaxTemperature); + this.minTemperature = (EditText) rootView.findViewById(R.id.editTextMinTemperature); + this.sunRise = (EditText) rootView.findViewById(R.id.editTextSunRise); + this.sunSet = (EditText) rootView.findViewById(R.id.editTextSunSet); + this.imageIcon = (ImageView) rootView.findViewById(R.id.imageIcon); + + return rootView; + } + + @Override + public void onClickGetWeather(final View v) { + + final IJPOSWeatherParser JPOSWeatherParser = new JPOSWeatherParser(); + final WeatherService weatherService = new WeatherService( + JPOSWeatherParser); + final AndroidHttpClient httpClient = AndroidHttpClient + .newInstance("Android Weather Information Agent"); + final WeatherHTTPClient HTTPweatherClient = new WeatherHTTPClient( + httpClient); + + final WeatherTask weatherTask = new WeatherTask(HTTPweatherClient, weatherService); + + final EditText cityCountry = (EditText) this.getActivity() + .findViewById(R.id.editTextCity); + + weatherTask.execute(cityCountry.getText().toString()); + } + + public void updateWeatherData(final WeatherData weatherData) { + final DecimalFormat tempFormatter = new DecimalFormat("#####.#####"); + final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss Z"); + final double tempUnits = this.isFahrenheit ? 0 : 273.15; + + if (weatherData.getWeather() != null) { + this.weatherDescription.setText(weatherData.getWeather() + .getDescription()); + double conversion = weatherData.getMain().getTemp(); + conversion = conversion - tempUnits; + this.temperature.setText(tempFormatter.format(conversion)); + conversion = weatherData.getMain().getMaxTemp(); + conversion = conversion - tempUnits; + this.maxTemperature.setText(tempFormatter.format(conversion)); + conversion = weatherData.getMain().getMinTemp(); + conversion = conversion - tempUnits; + this.minTemperature.setText(tempFormatter.format(conversion)); + } + + if (weatherData.getSystem() != null) { + long unixTime = weatherData.getSystem().getSunRiseTime(); + Date unixDate = new Date(unixTime * 1000L); + String dateFormatUnix = dateFormat.format(unixDate); + this.sunRise.setText(dateFormatUnix); + + unixTime = weatherData.getSystem().getSunSetTime(); + unixDate = new Date(unixTime * 1000L); + dateFormatUnix = dateFormat.format(unixDate); + this.sunSet.setText(dateFormatUnix); + } + + if (weatherData.getIconData() != null) { + final Bitmap icon = BitmapFactory.decodeByteArray( + weatherData.getIconData(), 0, + weatherData.getIconData().length); + this.imageIcon.setImageBitmap(icon); + } + } + + @Override + public void onResume() { + super.onResume(); + + final SharedPreferences sharedPreferences = PreferenceManager + .getDefaultSharedPreferences(this.getActivity()); + + final String unitsKey = this.getResources().getString( + R.string.weather_preferences_units_key); + final String units = sharedPreferences.getString(unitsKey, ""); + final String celsius = this.getResources().getString( + R.string.weather_preferences_units_celsius); + if (units.equals(celsius)) { + this.isFahrenheit = false; + } else { + this.isFahrenheit = true; + } + } + + public class WeatherTask extends AsyncTask { + private static final String TAG = "JSONWeatherTask"; + private final WeatherHTTPClient weatherHTTPClient; + private final WeatherService weatherService; + + public WeatherTask(final WeatherHTTPClient weatherHTTPClient, + final WeatherService weatherService) { + this.weatherHTTPClient = weatherHTTPClient; + this.weatherService = weatherService; + } + + @Override + protected WeatherData doInBackground(final Object... params) { + WeatherData weatherData = null; + + try { + weatherData = this.doInBackgroundThrowable(params); + } catch (final ClientProtocolException e) { + Log.e(TAG, "WeatherHTTPClient exception: ", e); + } catch (final MalformedURLException e) { + Log.e(TAG, "Syntax URL exception: ", e); + } catch (final URISyntaxException e) { + Log.e(TAG, "WeatherHTTPClient exception: ", e); + } catch (final IOException e) { + Log.e(TAG, "WeatherHTTPClient exception: ", e); + } catch (final JSONException e) { + Log.e(TAG, "WeatherService exception: ", e); + } finally { + this.weatherHTTPClient.close(); + } + + return weatherData; + } + + @Override + protected void onPostExecute(final WeatherData weatherData) { + if (weatherData != null) { + WeatherInformationDataFragmentDeprecated.this.updateWeatherData(weatherData); + } else { + ((ErrorMessage) WeatherInformationDataFragmentDeprecated.this.getActivity()) + .createErrorDialog(R.string.error_dialog_generic_error); + } + + this.weatherHTTPClient.close(); + } + + @Override + protected void onCancelled(final WeatherData weatherData) { + this.onCancelled(); + ((ErrorMessage) WeatherInformationDataFragmentDeprecated.this.getActivity()) + .createErrorDialog(R.string.error_dialog_connection_tiemout); + + this.weatherHTTPClient.close(); + } + + private WeatherData doInBackgroundThrowable(final Object... params) + throws ClientProtocolException, MalformedURLException, + URISyntaxException, IOException, JSONException { + final String cityCountry = (String) params[0]; + final String urlAPICity = WeatherInformationDataFragmentDeprecated.this.getResources() + .getString(R.string.uri_api_city); + final String APIVersion = WeatherInformationDataFragmentDeprecated.this.getResources() + .getString(R.string.api_version); + String url = this.weatherService.createURIAPICityCountry( + cityCountry, urlAPICity, APIVersion); + + + final String jsonData = this.weatherHTTPClient.retrieveJSONDataFromAPI(new URL(url)); + + + final WeatherData weatherData = this.weatherService.retrieveWeather(jsonData); + + + final String icon = weatherData.getWeather().getIcon(); + final String urlAPIicon = WeatherInformationDataFragmentDeprecated.this + .getResources().getString(R.string.uri_api_icon); + url = this.weatherService.createURIAPIicon(icon, urlAPIicon); + final byte[] iconData = this.weatherHTTPClient + .retrieveDataFromAPI(new URL(url)).toByteArray(); + weatherData.setIconData(iconData); + + + return weatherData; + } + } +}