Advertisement
Pablinski

Untitled

Apr 8th, 2015
314
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.70 KB | None | 0 0
  1. Hi all,
  2. I´m having problems refactoring SettingsActivity.java.
  3.  
  4. First, I extended PreferenceActivity but it didn't take
  5. addPreferencesFromResource(R.xml.pref_general) because it marks decaprecated as well as findPreference(getString(R.string.pref_location_key). I've changed to PreferenceFragment and it took both methods above but now cannot resolve getMenuInflater().inflate(R.menu.menu_settings, menu);
  6.  
  7. Furthermore it's showing: "cannot resolve symbol pref_units_keys" in
  8. bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key)));
  9.  
  10. Finally in the ForecastFragment.java I cannot get this method right:
  11.  
  12. private String formatHighLows(double high, double low){
  13. // Data is fetched in Celsius by default.
  14. // If user prefers to see in Fahrenheit, convert the values here.
  15. // We do this rather than fetching in Fahrenheit so that the user can
  16. // change this option without us having to re-fetch the data once
  17. // we start storing the values in the database
  18. SharedPreferences sharedPrefs =
  19. PreferenceManager.getDefaultSharedPreferences(getActivity());
  20. String unitType = sharedPrefs.getString(
  21. getString(R.string.pref_units_key),
  22. getString(R.string.pref_units_metric));
  23.  
  24. if(unitType.equals(getString(R.string.pref_units_imperial))){
  25. high = (high * 1.8) + 32;
  26. low = (low * 1.8) + 32;
  27. }else if(!unitType.equals(R.string.pref_units_metric)){
  28. Log.d(LOG_TAG, "Unit type not found: " + unitType);
  29. }
  30.  
  31. Probably I need to declare de units and metric in the string.xml file...
  32.  
  33. What can I do??
  34.  
  35. Here is my code:
  36.  
  37. SettingsActivity.java
  38.  
  39. package com.example.androidjppf.sunshine;
  40.  
  41. import android.os.Bundle;
  42. import android.preference.ListPreference;
  43. import android.preference.Preference;
  44. import android.preference.PreferenceActivity;
  45. import android.preference.PreferenceFragment;
  46. import android.preference.PreferenceManager;
  47. import android.support.v4.app.Fragment;
  48. import android.view.LayoutInflater;
  49. import android.view.Menu;
  50. import android.view.MenuItem;
  51. import android.view.View;
  52. import android.view.ViewGroup;
  53. import android.view.MenuInflater;
  54.  
  55. public class SettingsActivity extends PreferenceFragment
  56. implements Preference.OnPreferenceChangeListener {
  57.  
  58. @Override
  59. public void onCreate(Bundle savedInstanceState) {
  60. super.onCreate(savedInstanceState);
  61. /*setContentView(R.layout.activity_settings);
  62. if (savedInstanceState == null) {
  63. getSupportFragmentManager().beginTransaction()
  64. .add(R.id.container, new PlaceholderFragment())
  65. .commit();*/
  66. //Add general preferences, defined in the XML file
  67. addPreferencesFromResource(R.xml.pref_general);
  68.  
  69. //For all the preferences, attach an OnPreferenceChangeListener so the UI summary can be
  70. //updated when the preference changes
  71. //bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
  72. bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
  73. bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key)));
  74. }
  75.  
  76. /**
  77. * Attaches a listener so the summary is always updated with the preference value.
  78. * Also fires the listener once, to initialize the summary (so it shows up before the value
  79. * is changed.)
  80. */
  81. private void bindPreferenceSummaryToValue(Preference preference){
  82. //Set the listener to watch for value changes.
  83. preference.setOnPreferenceChangeListener(this);
  84.  
  85. //Trigger the listener immediately w/ preference's current value.
  86. onPreferenceChange(preference,
  87. PreferenceManager
  88. .getDefaultSharedPreferences(preference.getContext())
  89. .getString(preference.getKey(),""));
  90.  
  91. }
  92.  
  93. @Override
  94. public boolean onPreferenceChange(Preference preference, Object value){
  95. String stringValue = value.toString();
  96.  
  97. if(preference instanceof ListPreference){
  98. //For list preferences, look up the correct display value in
  99. //the preference's 'entries' list (since they have separate labels/values).
  100. ListPreference listPreference = (ListPreference) preference;
  101. int prefIndex = listPreference.findIndexOfValue(stringValue);
  102. if(prefIndex >= 0){
  103. preference.setSummary(listPreference.getEntries()[prefIndex]);
  104. }
  105. }else{
  106. //For other preferences, set the summary to the value's simple string representation
  107. preference.setSummary(stringValue);
  108. }
  109. return true;
  110. }
  111.  
  112. @Override
  113. public boolean onCreateOptionsMenu(Menu menu) {
  114. // Inflate the menu; this adds items to the action bar if it is present.
  115. getMenuInflater().inflate(R.menu.menu_settings, menu);
  116. return true;
  117. }
  118.  
  119. @Override
  120. public boolean onOptionsItemSelected(MenuItem item) {
  121. // Handle action bar item clicks here. The action bar will
  122. // automatically handle clicks on the Home/Up button, so long
  123. // as you specify a parent activity in AndroidManifest.xml.
  124. int id = item.getItemId();
  125.  
  126. //noinspection SimplifiableIfStatement
  127. if (id == R.id.action_settings) {
  128. return true;
  129. }
  130.  
  131. return super.onOptionsItemSelected(item);
  132. }
  133.  
  134. /**
  135. * A placeholder fragment containing a simple view.
  136. */
  137. public static class PlaceholderFragment extends Fragment {
  138.  
  139. public PlaceholderFragment() {
  140. }
  141.  
  142. @Override
  143. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  144. Bundle savedInstanceState) {
  145. View rootView = inflater.inflate(R.layout.fragment_settings, container, false);
  146. return rootView;
  147. }
  148. }
  149. }
  150. ###############################################
  151. ForecastFragment.java
  152.  
  153. package com.example.androidjppf.sunshine;
  154.  
  155. import android.content.Intent;
  156. import android.content.SharedPreferences;
  157. import android.net.Uri;
  158. import android.os.AsyncTask;
  159. import android.os.Bundle;
  160. import android.preference.PreferenceManager;
  161. import android.support.v4.app.Fragment;
  162. import android.text.format.Time;
  163. import android.util.Log;
  164. import android.view.LayoutInflater;
  165. import android.view.Menu;
  166. import android.view.MenuInflater;
  167. import android.view.MenuItem;
  168. import android.view.View;
  169. import android.view.ViewGroup;
  170. import android.widget.AdapterView;
  171. import android.widget.ArrayAdapter;
  172. import android.widget.ListView;
  173.  
  174. import org.json.JSONArray;
  175. import org.json.JSONException;
  176. import org.json.JSONObject;
  177.  
  178. import java.io.BufferedReader;
  179. import java.io.IOException;
  180. import java.io.InputStream;
  181. import java.io.InputStreamReader;
  182. import java.net.HttpURLConnection;
  183. import java.net.URL;
  184. import java.text.SimpleDateFormat;
  185. import java.util.ArrayList;
  186.  
  187. //import java.sql.Time;
  188.  
  189. /**
  190. * Created by JP on 21/01/2015.
  191. */
  192. //@TargetApi(Build.VERSION_CODES.HONEYCOMB)
  193. public class ForecastFragment extends Fragment {
  194.  
  195.  
  196. private ArrayAdapter<String> mForecastAdapter;
  197.  
  198. public ForecastFragment(){
  199. }
  200.  
  201. @Override
  202. public void onCreate(Bundle savedInstanceState){
  203. super.onCreate(savedInstanceState);
  204. //Add this line in order for this fragment to handle menu events
  205. setHasOptionsMenu(true);
  206. }
  207.  
  208. @Override
  209. public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
  210. inflater.inflate(R.menu.forecastfrafment, menu);
  211. }
  212.  
  213. @Override
  214. public boolean onOptionsItemSelected(MenuItem item){
  215. //Handle action bar item clicks here, The action bar will
  216. //automatically handle clicks on the Home/Up button, so long
  217. //as you specify a parent activity in AndroidManifest.xml
  218.  
  219. /*int id = item.getItemId();
  220. if(id == R.id.action_refresh){
  221. FetchWeatherTask weatherTask = new FetchWeatherTask();
  222. weatherTask.execute("94043");
  223. return true;
  224. }
  225. return super.onOptionsItemSelected(item);
  226.  
  227. int id = item.getItemId();
  228. if(id == R.id.action_refresh){
  229. FetchWeatherTask weatherTask = new FetchWeatherTask();
  230. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
  231. String location = prefs.getString(getString(R.string.pref_location_key),
  232. getString(R.string.pref_location_default));
  233. weatherTask.execute(location);
  234. return true;
  235. }
  236. return super.onOptionsItemSelected(item);*/
  237. int id = item.getItemId();
  238. if(id == R.id.action_refresh){
  239. updateWeather();
  240. return true;
  241. }
  242. return super.onOptionsItemSelected(item);
  243. }
  244.  
  245.  
  246. @Override
  247. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  248. Bundle savedInstanceState) {
  249. //cancelled
  250. //Create some dummy data for the ListView. Here´s a sample weekly forecast
  251. View rootView = inflater.inflate(R.layout.fragment_main, container, false);
  252.  
  253. /*String[] forecastArray = {"Today - Sunny - 88/63",
  254. "Tomorrow - Foggy - 70/40",
  255. "Weds - Cloudy - 72/63",
  256. "Thurs - Asteroids - 75/65",
  257. "Fri - Heavy Rain - 65/56",
  258. "Sat - HELP TRAPPED IN WEATHERSITUATION - 65/51",
  259. "Sun - Sunny - 88/68"};
  260. */
  261.  
  262. //List<String> weekForecast = new ArrayList<String>(Arrays.asList(forecastArray));
  263.  
  264. //cancelled
  265. //Now that we have some dummy forecast data. create an ArrayAdapter.
  266. //This will take data from the source (our dummy forecast)
  267. //Use it to populate the ListView it's attached to
  268.  
  269. // ArrayAdapter<String>
  270. // The arrayAdapter will take data from a source and
  271. //use it to populate the ListView it's attached to.
  272. mForecastAdapter = new ArrayAdapter<String>(
  273. //The current context (fragment´s parent activity)
  274. getActivity(), //the current context (this activity)
  275. //ID of list item layout
  276. R.layout.list_item_forecast, //the name of the layout id
  277. //ID of the textview to populate
  278. R.id.list_item_forecast_textview, //the name of the textview to populate
  279. //Forecast data
  280. //weekForecast);
  281. new ArrayList<String>());
  282. //Get a reference to ListView and attach this adapter to it
  283. ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast);
  284. listView.setAdapter(mForecastAdapter);
  285. listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  286. @Override
  287. public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
  288. //Display toast getting the Forecast through the mForecastAdapter
  289. String forecast = mForecastAdapter.getItem(position);
  290. //Toast.makeText(getActivity(), forecast, Toast.LENGTH_SHORT).show();
  291. Intent intent = new Intent(getActivity(), DetailActivity.class)
  292. .putExtra(Intent.EXTRA_TEXT, forecast);
  293. startActivity(intent);
  294. }
  295. });
  296.  
  297. return rootView;
  298. }
  299.  
  300. private void updateWeather(){
  301. FetchWeatherTask weatherTask = new FetchWeatherTask();
  302. String location = PreferenceManager.getDefaultSharedPreferences(getActivity())
  303. .getString(getString(R.string.pref_location_key), getString(R.string.pref_location_default));
  304. weatherTask.execute(location);
  305. }
  306.  
  307. //Updates weather when the fragment starts
  308. @Override
  309. public void onStart(){
  310. super.onStart();
  311. updateWeather();
  312. }
  313.  
  314. public class FetchWeatherTask extends AsyncTask<String, Void, String[]> {
  315.  
  316. private final String LOG_TAG = FetchWeatherTask.class.getSimpleName();
  317.  
  318. /*The date/time conversion code is going to be moved outside the asynctask later,
  319. *So for convenience we´re breaking it out into its own method now.
  320. */
  321. private String getReadableDateString(long time){
  322. //Because the API returns a UNIX timestamp (measured in seconds),
  323. //it must be converted to milliseconds in order to be converted to valid date.
  324. SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE MM dd");
  325. return shortenedDateFormat.format(time);
  326. }
  327.  
  328. /* Prepare the weather high/lows for presentation
  329. *
  330. */
  331. private String formatHighLows(double high, double low){
  332. // Data is fetched in Celsius by default.
  333. // If user prefers to see in Fahrenheit, convert the values here.
  334. // We do this rather than fetching in Fahrenheit so that the user can
  335. // change this option without us having to re-fetch the data once
  336. // we start storing the values in the database
  337. SharedPreferences sharedPrefs =
  338. PreferenceManager.getDefaultSharedPreferences(getActivity());
  339. String unitType = sharedPrefs.getString(
  340. getString(R.string.pref_units_key),
  341. getString(R.string.pref_units_metric));
  342.  
  343. if(unitType.equals(getString(R.string.pref_units_imperial))){
  344. high = (high * 1.8) + 32;
  345. low = (low * 1.8) + 32;
  346. }else if(!unitType.equals(R.string.pref_units_metric)){
  347. Log.d(LOG_TAG, "Unit type not found: " + unitType);
  348. }
  349.  
  350.  
  351. // For presentation, assume the user doesn't care about tenths of a degree.
  352. long roundedHigh = Math.round(high);
  353. long roundedLow = Math.round(low);
  354. String highLowStr = roundedHigh + "/" + roundedLow;
  355. return highLowStr;
  356. }
  357. //Take the string representing the complete forecast in JSON Format and
  358. //pull out the data we need to construct the Strings needed for the wireframes.
  359. //
  360. //Fortunately parsing is easy: constructor takes the JSON string and converts it
  361. //into an Object hierarchy for us.
  362. private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays)
  363. throws JSONException{
  364.  
  365. //These are the names of the JSON objects that need to be extracted.
  366. final String OWN_LIST = "list";
  367. final String OWN_WEATHER = "weather";
  368. final String OWN_TEMPERATURE = "temp";
  369. final String OWN_MAX = "max";
  370. final String OWN_MIN = "min";
  371. final String OWN_DESCRIPTION = "main";
  372.  
  373. JSONObject forecastJson = new JSONObject(forecastJsonStr);
  374. JSONArray weatherArray = forecastJson.getJSONArray(OWN_LIST);
  375.  
  376. //OWN returns daily forecasts based upon the local time of the city that is being
  377. //asked for, which means that we need to know the GMT offset to translate this data
  378. //properly
  379.  
  380. //Since this data is also sent in-order and the first day is always the current
  381. //day , we´re going to take advantage of that to get a nice normalized
  382. //UTC date for all our weather
  383.  
  384. Time dayTime = new Time();
  385. dayTime.setToNow();
  386.  
  387. //We start at the day returned by local time. Otherwise this is a mess
  388. int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff);
  389.  
  390. //now we work exclusively in UTC
  391. dayTime = new Time();
  392.  
  393. String[] resultStrs = new String[numDays];
  394. for(int i = 0; i < weatherArray.length(); i++){
  395. //for now using the format "Day, description high/low"
  396. String day;
  397. String description;
  398. String highAndLow;
  399.  
  400. //Set JSON object representing the day
  401. JSONObject dayForecast = weatherArray.getJSONObject(i);
  402.  
  403. //The date/time is returned as a long. We need to convert that
  404. //into something human-readable, since most people won´t "1400356800"
  405. //as this Saturday
  406. long dateTime;
  407. //Cheating to convert this UTC time, which is what we want anyhow
  408. dateTime = dayTime.setJulianDay(julianStartDay+i);
  409. day = getReadableDateString(dateTime);
  410.  
  411. //description is in a child array called "weather", which is 1 element long.
  412. JSONObject weatherObject = dayForecast.getJSONArray(OWN_WEATHER).getJSONObject(0);
  413. description = weatherObject.getString(OWN_DESCRIPTION);
  414.  
  415. //Temperatures are in a child object called "temp". Try not to name variables
  416. //temp when working with temperature. It confuses everybody.
  417. JSONObject temperatureObject = dayForecast.getJSONObject(OWN_TEMPERATURE);
  418. double high = temperatureObject.getDouble(OWN_MAX);
  419. double low = temperatureObject.getDouble(OWN_MIN);
  420.  
  421. highAndLow = formatHighLows(high, low);
  422. resultStrs[i] = day + " - " + description + " - " + highAndLow;
  423. }
  424.  
  425. /*for(String s : resultStrs){
  426. Log.v(LOG_TAG, "Forecast entry: " + s);
  427. }*/
  428.  
  429. return resultStrs;
  430. }
  431.  
  432. @Override
  433. protected String[] doInBackground(String... params) {
  434.  
  435. //If there is no zip code, there is nothing to look up. Verify size of params.
  436. if (params.length == 0){
  437. return null;
  438. }
  439.  
  440. // These two need to be declared outside the try/catch
  441. // so that they can be closed in the finally block.
  442. HttpURLConnection urlConnection = null;
  443. BufferedReader reader = null;
  444.  
  445. // Will contain the raw JSON response as a string.
  446. String forecastJsonStr = null;
  447.  
  448. String format = "json";
  449. String units = "metric";
  450. int numDays = 7;
  451.  
  452. try {
  453. // Construct the URL for the OpenWeatherMap query
  454. // Possible parameters are available at OWM's forecast API page, at
  455. // http://openweathermap.org/API#forecast
  456. final String FORECAST_BASE_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?";
  457. final String QUERY_PARAM = "q";
  458. final String FORMAT_PARAM = "mode";
  459. final String UNITS_PARAM = "units";
  460. final String DAYS_PARAM = "cnt";
  461. //URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7");
  462.  
  463. Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon()
  464. .appendQueryParameter(QUERY_PARAM, params[0])
  465. .appendQueryParameter(FORMAT_PARAM, format)
  466. .appendQueryParameter(UNITS_PARAM, units)
  467. .appendQueryParameter(DAYS_PARAM, Integer.toString(numDays))
  468. .build();
  469.  
  470. URL url = new URL(builtUri.toString());
  471.  
  472. //Log.v(LOG_TAG, "Built URI " + builtUri.toString());
  473.  
  474. // Create the request to OpenWeatherMap, and open the connection
  475. urlConnection = (HttpURLConnection) url.openConnection();
  476. urlConnection.setRequestMethod("GET");
  477. urlConnection.connect();
  478.  
  479. // Read the input stream into a String
  480. InputStream inputStream = urlConnection.getInputStream();
  481. StringBuffer buffer = new StringBuffer();
  482. if (inputStream == null) {
  483. // Nothing to do.
  484. //forecastJsonStr = null;
  485. return null;
  486. }
  487. reader = new BufferedReader(new InputStreamReader(inputStream));
  488.  
  489. String line;
  490. while ((line = reader.readLine()) != null) {
  491. // Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
  492. // But it does make debugging a *lot* easier if you print out the completed
  493. // buffer for debugging.
  494. buffer.append(line + "\n");
  495. }
  496.  
  497. if (buffer.length() == 0) {
  498. // Stream was empty. No point in parsing.
  499. //forecastJsonStr = null;
  500. return null;
  501. }
  502. forecastJsonStr = buffer.toString();
  503.  
  504. //Log.v(LOG_TAG, "Forecast JSON String: " + forecastJsonStr);
  505.  
  506. } catch (IOException e) {
  507. Log.e(LOG_TAG, "Error ", e);
  508. // If the code didn't successfully get the weather data, there's no point in attempting
  509. // to parse it.
  510. //forecastJsonStr = null;
  511. return null;
  512. } finally {
  513. if (urlConnection != null) {
  514. urlConnection.disconnect();
  515. }
  516. if (reader != null) {
  517. try {
  518. reader.close();
  519. } catch (final IOException e) {
  520. Log.e(LOG_TAG, "Error closing stream", e);
  521. }
  522. }
  523. }
  524. try {
  525. return getWeatherDataFromJson(forecastJsonStr, numDays);
  526. }catch (JSONException e){
  527. Log.e(LOG_TAG, e.getMessage(), e);
  528. e.printStackTrace();
  529. }
  530. // This will only happen if there was an error getting or parsing the forecast.
  531. return null;
  532. }
  533.  
  534. @Override
  535. protected void onPostExecute(String[] resultStr) {
  536. if(resultStr != null){
  537. mForecastAdapter.clear();
  538. for(String dayForecastStr : resultStr){
  539. mForecastAdapter.add(dayForecastStr);
  540. }
  541. //New data is back from server. Hooray!
  542. }
  543. }
  544. }
  545. }
  546. ##########################################
  547. pref_general.xml
  548.  
  549. <?xml version="1.0" encoding="utf-8"?>
  550. <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
  551. android:layout_width="match_parent"
  552. android:layout_height="match_parent">
  553.  
  554. <EditTextPreference
  555. android:title="@string/pref_location_label"
  556. android:key="@string/pref_location_key"
  557. android:defaultValue="@string/pref_location_default"
  558. android:inputType="text"
  559. android:singleLine="true" />
  560.  
  561. <ListPreference
  562. android:title="@string/pref_units_label"
  563. android:key="@string/pref_units_key"
  564. android:defaultValue="@string/pref_units_metric"
  565. android:entryValues="@array/pref_units_values"
  566. android:entries="@array/pref_units_options" />
  567. </PreferenceScreen>
  568. ######################################
  569. THX IN ADVANCED
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement