d78c7057941be6cb4d1ecc33630d2d26bdc1b2b1
[Sunshine.git] / app / src / main / java / uk / me / njae / sunshine / ForecastFragment.java
1 package uk.me.njae.sunshine;
2
3 import android.content.Intent;
4 import android.content.SharedPreferences;
5 import android.database.Cursor;
6 import android.net.Uri;
7 import android.os.Bundle;
8 import android.preference.PreferenceManager;
9 import android.support.v4.app.Fragment;
10 import android.support.v4.app.LoaderManager;
11 import android.support.v4.content.CursorLoader;
12 import android.support.v4.content.Loader;
13 import android.support.v4.widget.SimpleCursorAdapter;
14 import android.util.Log;
15 import android.view.LayoutInflater;
16 import android.view.Menu;
17 import android.view.MenuInflater;
18 import android.view.MenuItem;
19 import android.view.View;
20 import android.view.ViewGroup;
21 import android.widget.AdapterView;
22 import android.widget.ListView;
23
24 import java.io.UnsupportedEncodingException;
25 import java.net.URLEncoder;
26 import java.util.Date;
27
28 import uk.me.njae.sunshine.data.WeatherContract;
29 import uk.me.njae.sunshine.data.WeatherContract.LocationEntry;
30 import uk.me.njae.sunshine.data.WeatherContract.WeatherEntry;
31
32 /**
33 * A placeholder fragment containing a simple view.
34 */
35 public class ForecastFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
36
37 private final String LOG_TAG = ForecastFragment.class.getSimpleName();
38
39 private SimpleCursorAdapter mForecastAdapter;
40
41 private static final int FORECAST_LOADER = 0;
42 private String mLocation;
43
44 // For the forecast view we're showing only a small subset of the stored data.
45 // Specify the columns we need.
46 private static final String[] FORECAST_COLUMNS = {
47 // In this case the id needs to be fully qualified with a table name, since
48 // the content provider joins the location & weather tables in the background
49 // (both have an _id column)
50 // On the one hand, that's annoying. On the other, you can search the weather table
51 // using the location set by the user, which is only in the Location table.
52 // So the convenience is worth it.
53 WeatherEntry.TABLE_NAME + "." + WeatherEntry._ID,
54 WeatherEntry.COLUMN_DATETEXT,
55 WeatherEntry.COLUMN_SHORT_DESC,
56 WeatherEntry.COLUMN_MAX_TEMP,
57 WeatherEntry.COLUMN_MIN_TEMP,
58 LocationEntry.COLUMN_LOCATION_SETTING
59 };
60
61 // These indices are tied to FORECAST_COLUMNS. If FORECAST_COLUMNS changes, these
62 // must change.
63 public static final int COL_WEATHER_ID = 0;
64 public static final int COL_WEATHER_DATE = 1;
65 public static final int COL_WEATHER_DESC = 2;
66 public static final int COL_WEATHER_MAX_TEMP = 3;
67 public static final int COL_WEATHER_MIN_TEMP = 4;
68 public static final int COL_LOCATION_SETTING = 5;
69
70 public ForecastFragment() {
71 }
72
73 @Override
74 public void onCreate(Bundle savedInstanceState) {
75 super.onCreate(savedInstanceState);
76 setHasOptionsMenu(true);
77 }
78
79 @Override
80 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
81 // Inflate the menu; this adds items to the action bar if it is present.
82 inflater.inflate(R.menu.forecastfragment, menu);
83 }
84
85 @Override
86 public boolean onOptionsItemSelected(MenuItem item) {
87 // Handle action bar item clicks here. The action bar will
88 // automatically handle clicks on the Home/Up button, so long
89 // as you specify a parent activity in AndroidManifest.xml.
90 int id = item.getItemId();
91 if (id == R.id.action_refresh) {
92 updateWeather();
93 return true;
94 }
95 if (id == R.id.action_show_location) {
96 SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
97 String location = preferences.getString(getString(R.string.pref_location_key),
98 getString(R.string.pref_location_default));
99 Intent intent = new Intent(Intent.ACTION_VIEW);
100 Uri geoLocation;
101 try {
102 geoLocation = Uri.parse("geo:0,0?q=" + URLEncoder.encode(location, "UTF-8"));
103 intent.setData(geoLocation);
104 } catch (UnsupportedEncodingException e) {
105 Log.e(LOG_TAG, "Error ", e);
106 }
107 if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
108 startActivity(intent);
109 }
110
111 }
112 return super.onOptionsItemSelected(item);
113 }
114
115 @Override
116 public void onActivityCreated(Bundle savedInstanceState) {
117 getLoaderManager().initLoader(FORECAST_LOADER, null, this);
118 super.onActivityCreated(savedInstanceState);
119 }
120
121 private void updateWeather() {
122 String location = Utility.getPreferredLocation(getActivity());
123 new FetchWeatherTask(getActivity()).execute(location);
124 }
125
126 @Override
127 public View onCreateView(LayoutInflater inflater, ViewGroup container,
128 Bundle savedInstanceState) {
129 // The SimpleCursorAdapter will take data from the database through the
130 // Loader and use it to populate the ListView it's attached to.
131 mForecastAdapter = new SimpleCursorAdapter(
132 getActivity(),
133 R.layout.list_item_forecast,
134 null,
135 // the column names to use to fill the textviews
136 new String[]{WeatherContract.WeatherEntry.COLUMN_DATETEXT,
137 WeatherContract.WeatherEntry.COLUMN_SHORT_DESC,
138 WeatherContract.WeatherEntry.COLUMN_MAX_TEMP,
139 WeatherContract.WeatherEntry.COLUMN_MIN_TEMP
140 },
141 // the textviews to fill with the data pulled from the columns above
142 new int[]{R.id.list_item_date_textview,
143 R.id.list_item_forecast_textview,
144 R.id.list_item_high_textview,
145 R.id.list_item_low_textview
146 },
147 0
148 );
149
150 View rootView = inflater.inflate(R.layout.fragment_main, container, false);
151
152 ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast);
153 listView.setAdapter(mForecastAdapter);
154 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
155
156 @Override
157 public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
158 // String forecast = mForecastAdapter.getItem(position);
159 Intent intent = new Intent(getActivity(), DetailActivity.class)
160 .putExtra(Intent.EXTRA_TEXT, "placeholder");
161 startActivity(intent);
162 }
163 });
164
165 return rootView;
166 }
167
168 public void onStart() {
169 super.onStart();
170 updateWeather();
171 }
172
173 @Override
174 public Loader<Cursor> onCreateLoader(int id, Bundle args) {
175 // This is called when a new Loader needs to be created. This
176 // fragment only uses one loader, so we don't care about checking the id.
177
178 // To only show current and future dates, get the String representation for today,
179 // and filter the query to return weather only for dates after or including today.
180 // Only return data after today.
181 String startDate = WeatherContract.getDbDateString(new Date());
182
183 // Sort order: Ascending, by date.
184 String sortOrder = WeatherEntry.COLUMN_DATETEXT + " ASC";
185
186 mLocation = Utility.getPreferredLocation(getActivity());
187 Uri weatherForLocationUri = WeatherEntry.buildWeatherLocationWithStartDate(
188 mLocation, startDate);
189
190 // Now create and return a CursorLoader that will take care of
191 // creating a Cursor for the data being displayed.
192 return new CursorLoader(
193 getActivity(),
194 weatherForLocationUri,
195 FORECAST_COLUMNS,
196 null,
197 null,
198 sortOrder
199 );
200 }
201
202 @Override
203 public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
204 mForecastAdapter.swapCursor(data);
205 }
206
207 @Override
208 public void onLoaderReset(Loader<Cursor> loader) {
209 mForecastAdapter.swapCursor(null);
210 }
211 }