Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Hi all,
- I´m having problems refactoring SettingsActivity.java.
- First, I extended PreferenceActivity but it didn't take
- 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);
- Furthermore it's showing: "cannot resolve symbol pref_units_keys" in
- bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key)));
- Finally in the ForecastFragment.java I cannot get this method right:
- private String formatHighLows(double high, double low){
- // Data is fetched in Celsius by default.
- // If user prefers to see in Fahrenheit, convert the values here.
- // We do this rather than fetching in Fahrenheit so that the user can
- // change this option without us having to re-fetch the data once
- // we start storing the values in the database
- SharedPreferences sharedPrefs =
- PreferenceManager.getDefaultSharedPreferences(getActivity());
- String unitType = sharedPrefs.getString(
- getString(R.string.pref_units_key),
- getString(R.string.pref_units_metric));
- if(unitType.equals(getString(R.string.pref_units_imperial))){
- high = (high * 1.8) + 32;
- low = (low * 1.8) + 32;
- }else if(!unitType.equals(R.string.pref_units_metric)){
- Log.d(LOG_TAG, "Unit type not found: " + unitType);
- }
- Probably I need to declare de units and metric in the string.xml file...
- What can I do??
- Here is my code:
- SettingsActivity.java
- package com.example.androidjppf.sunshine;
- import android.os.Bundle;
- import android.preference.ListPreference;
- import android.preference.Preference;
- import android.preference.PreferenceActivity;
- import android.preference.PreferenceFragment;
- import android.preference.PreferenceManager;
- import android.support.v4.app.Fragment;
- import android.view.LayoutInflater;
- import android.view.Menu;
- import android.view.MenuItem;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.MenuInflater;
- public class SettingsActivity extends PreferenceFragment
- implements Preference.OnPreferenceChangeListener {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- /*setContentView(R.layout.activity_settings);
- if (savedInstanceState == null) {
- getSupportFragmentManager().beginTransaction()
- .add(R.id.container, new PlaceholderFragment())
- .commit();*/
- //Add general preferences, defined in the XML file
- addPreferencesFromResource(R.xml.pref_general);
- //For all the preferences, attach an OnPreferenceChangeListener so the UI summary can be
- //updated when the preference changes
- //bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
- bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_location_key)));
- bindPreferenceSummaryToValue(findPreference(getString(R.string.pref_units_key)));
- }
- /**
- * Attaches a listener so the summary is always updated with the preference value.
- * Also fires the listener once, to initialize the summary (so it shows up before the value
- * is changed.)
- */
- private void bindPreferenceSummaryToValue(Preference preference){
- //Set the listener to watch for value changes.
- preference.setOnPreferenceChangeListener(this);
- //Trigger the listener immediately w/ preference's current value.
- onPreferenceChange(preference,
- PreferenceManager
- .getDefaultSharedPreferences(preference.getContext())
- .getString(preference.getKey(),""));
- }
- @Override
- public boolean onPreferenceChange(Preference preference, Object value){
- String stringValue = value.toString();
- if(preference instanceof ListPreference){
- //For list preferences, look up the correct display value in
- //the preference's 'entries' list (since they have separate labels/values).
- ListPreference listPreference = (ListPreference) preference;
- int prefIndex = listPreference.findIndexOfValue(stringValue);
- if(prefIndex >= 0){
- preference.setSummary(listPreference.getEntries()[prefIndex]);
- }
- }else{
- //For other preferences, set the summary to the value's simple string representation
- preference.setSummary(stringValue);
- }
- return true;
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.menu_settings, menu);
- return true;
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
- //noinspection SimplifiableIfStatement
- if (id == R.id.action_settings) {
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
- /**
- * A placeholder fragment containing a simple view.
- */
- public static class PlaceholderFragment extends Fragment {
- public PlaceholderFragment() {
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View rootView = inflater.inflate(R.layout.fragment_settings, container, false);
- return rootView;
- }
- }
- }
- ###############################################
- ForecastFragment.java
- package com.example.androidjppf.sunshine;
- import android.content.Intent;
- import android.content.SharedPreferences;
- import android.net.Uri;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.preference.PreferenceManager;
- import android.support.v4.app.Fragment;
- import android.text.format.Time;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.Menu;
- import android.view.MenuInflater;
- import android.view.MenuItem;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.AdapterView;
- import android.widget.ArrayAdapter;
- import android.widget.ListView;
- import org.json.JSONArray;
- import org.json.JSONException;
- import org.json.JSONObject;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- //import java.sql.Time;
- /**
- * Created by JP on 21/01/2015.
- */
- //@TargetApi(Build.VERSION_CODES.HONEYCOMB)
- public class ForecastFragment extends Fragment {
- private ArrayAdapter<String> mForecastAdapter;
- public ForecastFragment(){
- }
- @Override
- public void onCreate(Bundle savedInstanceState){
- super.onCreate(savedInstanceState);
- //Add this line in order for this fragment to handle menu events
- setHasOptionsMenu(true);
- }
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
- inflater.inflate(R.menu.forecastfrafment, menu);
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item){
- //Handle action bar item clicks here, The action bar will
- //automatically handle clicks on the Home/Up button, so long
- //as you specify a parent activity in AndroidManifest.xml
- /*int id = item.getItemId();
- if(id == R.id.action_refresh){
- FetchWeatherTask weatherTask = new FetchWeatherTask();
- weatherTask.execute("94043");
- return true;
- }
- return super.onOptionsItemSelected(item);
- int id = item.getItemId();
- if(id == R.id.action_refresh){
- FetchWeatherTask weatherTask = new FetchWeatherTask();
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
- String location = prefs.getString(getString(R.string.pref_location_key),
- getString(R.string.pref_location_default));
- weatherTask.execute(location);
- return true;
- }
- return super.onOptionsItemSelected(item);*/
- int id = item.getItemId();
- if(id == R.id.action_refresh){
- updateWeather();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- //cancelled
- //Create some dummy data for the ListView. Here´s a sample weekly forecast
- View rootView = inflater.inflate(R.layout.fragment_main, container, false);
- /*String[] forecastArray = {"Today - Sunny - 88/63",
- "Tomorrow - Foggy - 70/40",
- "Weds - Cloudy - 72/63",
- "Thurs - Asteroids - 75/65",
- "Fri - Heavy Rain - 65/56",
- "Sat - HELP TRAPPED IN WEATHERSITUATION - 65/51",
- "Sun - Sunny - 88/68"};
- */
- //List<String> weekForecast = new ArrayList<String>(Arrays.asList(forecastArray));
- //cancelled
- //Now that we have some dummy forecast data. create an ArrayAdapter.
- //This will take data from the source (our dummy forecast)
- //Use it to populate the ListView it's attached to
- // ArrayAdapter<String>
- // The arrayAdapter will take data from a source and
- //use it to populate the ListView it's attached to.
- mForecastAdapter = new ArrayAdapter<String>(
- //The current context (fragment´s parent activity)
- getActivity(), //the current context (this activity)
- //ID of list item layout
- R.layout.list_item_forecast, //the name of the layout id
- //ID of the textview to populate
- R.id.list_item_forecast_textview, //the name of the textview to populate
- //Forecast data
- //weekForecast);
- new ArrayList<String>());
- //Get a reference to ListView and attach this adapter to it
- ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast);
- listView.setAdapter(mForecastAdapter);
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
- //Display toast getting the Forecast through the mForecastAdapter
- String forecast = mForecastAdapter.getItem(position);
- //Toast.makeText(getActivity(), forecast, Toast.LENGTH_SHORT).show();
- Intent intent = new Intent(getActivity(), DetailActivity.class)
- .putExtra(Intent.EXTRA_TEXT, forecast);
- startActivity(intent);
- }
- });
- return rootView;
- }
- private void updateWeather(){
- FetchWeatherTask weatherTask = new FetchWeatherTask();
- String location = PreferenceManager.getDefaultSharedPreferences(getActivity())
- .getString(getString(R.string.pref_location_key), getString(R.string.pref_location_default));
- weatherTask.execute(location);
- }
- //Updates weather when the fragment starts
- @Override
- public void onStart(){
- super.onStart();
- updateWeather();
- }
- public class FetchWeatherTask extends AsyncTask<String, Void, String[]> {
- private final String LOG_TAG = FetchWeatherTask.class.getSimpleName();
- /*The date/time conversion code is going to be moved outside the asynctask later,
- *So for convenience we´re breaking it out into its own method now.
- */
- private String getReadableDateString(long time){
- //Because the API returns a UNIX timestamp (measured in seconds),
- //it must be converted to milliseconds in order to be converted to valid date.
- SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE MM dd");
- return shortenedDateFormat.format(time);
- }
- /* Prepare the weather high/lows for presentation
- *
- */
- private String formatHighLows(double high, double low){
- // Data is fetched in Celsius by default.
- // If user prefers to see in Fahrenheit, convert the values here.
- // We do this rather than fetching in Fahrenheit so that the user can
- // change this option without us having to re-fetch the data once
- // we start storing the values in the database
- SharedPreferences sharedPrefs =
- PreferenceManager.getDefaultSharedPreferences(getActivity());
- String unitType = sharedPrefs.getString(
- getString(R.string.pref_units_key),
- getString(R.string.pref_units_metric));
- if(unitType.equals(getString(R.string.pref_units_imperial))){
- high = (high * 1.8) + 32;
- low = (low * 1.8) + 32;
- }else if(!unitType.equals(R.string.pref_units_metric)){
- Log.d(LOG_TAG, "Unit type not found: " + unitType);
- }
- // For presentation, assume the user doesn't care about tenths of a degree.
- long roundedHigh = Math.round(high);
- long roundedLow = Math.round(low);
- String highLowStr = roundedHigh + "/" + roundedLow;
- return highLowStr;
- }
- //Take the string representing the complete forecast in JSON Format and
- //pull out the data we need to construct the Strings needed for the wireframes.
- //
- //Fortunately parsing is easy: constructor takes the JSON string and converts it
- //into an Object hierarchy for us.
- private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays)
- throws JSONException{
- //These are the names of the JSON objects that need to be extracted.
- final String OWN_LIST = "list";
- final String OWN_WEATHER = "weather";
- final String OWN_TEMPERATURE = "temp";
- final String OWN_MAX = "max";
- final String OWN_MIN = "min";
- final String OWN_DESCRIPTION = "main";
- JSONObject forecastJson = new JSONObject(forecastJsonStr);
- JSONArray weatherArray = forecastJson.getJSONArray(OWN_LIST);
- //OWN returns daily forecasts based upon the local time of the city that is being
- //asked for, which means that we need to know the GMT offset to translate this data
- //properly
- //Since this data is also sent in-order and the first day is always the current
- //day , we´re going to take advantage of that to get a nice normalized
- //UTC date for all our weather
- Time dayTime = new Time();
- dayTime.setToNow();
- //We start at the day returned by local time. Otherwise this is a mess
- int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff);
- //now we work exclusively in UTC
- dayTime = new Time();
- String[] resultStrs = new String[numDays];
- for(int i = 0; i < weatherArray.length(); i++){
- //for now using the format "Day, description high/low"
- String day;
- String description;
- String highAndLow;
- //Set JSON object representing the day
- JSONObject dayForecast = weatherArray.getJSONObject(i);
- //The date/time is returned as a long. We need to convert that
- //into something human-readable, since most people won´t "1400356800"
- //as this Saturday
- long dateTime;
- //Cheating to convert this UTC time, which is what we want anyhow
- dateTime = dayTime.setJulianDay(julianStartDay+i);
- day = getReadableDateString(dateTime);
- //description is in a child array called "weather", which is 1 element long.
- JSONObject weatherObject = dayForecast.getJSONArray(OWN_WEATHER).getJSONObject(0);
- description = weatherObject.getString(OWN_DESCRIPTION);
- //Temperatures are in a child object called "temp". Try not to name variables
- //temp when working with temperature. It confuses everybody.
- JSONObject temperatureObject = dayForecast.getJSONObject(OWN_TEMPERATURE);
- double high = temperatureObject.getDouble(OWN_MAX);
- double low = temperatureObject.getDouble(OWN_MIN);
- highAndLow = formatHighLows(high, low);
- resultStrs[i] = day + " - " + description + " - " + highAndLow;
- }
- /*for(String s : resultStrs){
- Log.v(LOG_TAG, "Forecast entry: " + s);
- }*/
- return resultStrs;
- }
- @Override
- protected String[] doInBackground(String... params) {
- //If there is no zip code, there is nothing to look up. Verify size of params.
- if (params.length == 0){
- return null;
- }
- // These two need to be declared outside the try/catch
- // so that they can be closed in the finally block.
- HttpURLConnection urlConnection = null;
- BufferedReader reader = null;
- // Will contain the raw JSON response as a string.
- String forecastJsonStr = null;
- String format = "json";
- String units = "metric";
- int numDays = 7;
- try {
- // Construct the URL for the OpenWeatherMap query
- // Possible parameters are available at OWM's forecast API page, at
- // http://openweathermap.org/API#forecast
- final String FORECAST_BASE_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?";
- final String QUERY_PARAM = "q";
- final String FORMAT_PARAM = "mode";
- final String UNITS_PARAM = "units";
- final String DAYS_PARAM = "cnt";
- //URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7");
- Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon()
- .appendQueryParameter(QUERY_PARAM, params[0])
- .appendQueryParameter(FORMAT_PARAM, format)
- .appendQueryParameter(UNITS_PARAM, units)
- .appendQueryParameter(DAYS_PARAM, Integer.toString(numDays))
- .build();
- URL url = new URL(builtUri.toString());
- //Log.v(LOG_TAG, "Built URI " + builtUri.toString());
- // Create the request to OpenWeatherMap, and open the connection
- urlConnection = (HttpURLConnection) url.openConnection();
- urlConnection.setRequestMethod("GET");
- urlConnection.connect();
- // Read the input stream into a String
- InputStream inputStream = urlConnection.getInputStream();
- StringBuffer buffer = new StringBuffer();
- if (inputStream == null) {
- // Nothing to do.
- //forecastJsonStr = null;
- return null;
- }
- reader = new BufferedReader(new InputStreamReader(inputStream));
- String line;
- while ((line = reader.readLine()) != null) {
- // Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
- // But it does make debugging a *lot* easier if you print out the completed
- // buffer for debugging.
- buffer.append(line + "\n");
- }
- if (buffer.length() == 0) {
- // Stream was empty. No point in parsing.
- //forecastJsonStr = null;
- return null;
- }
- forecastJsonStr = buffer.toString();
- //Log.v(LOG_TAG, "Forecast JSON String: " + forecastJsonStr);
- } catch (IOException e) {
- Log.e(LOG_TAG, "Error ", e);
- // If the code didn't successfully get the weather data, there's no point in attempting
- // to parse it.
- //forecastJsonStr = null;
- return null;
- } finally {
- if (urlConnection != null) {
- urlConnection.disconnect();
- }
- if (reader != null) {
- try {
- reader.close();
- } catch (final IOException e) {
- Log.e(LOG_TAG, "Error closing stream", e);
- }
- }
- }
- try {
- return getWeatherDataFromJson(forecastJsonStr, numDays);
- }catch (JSONException e){
- Log.e(LOG_TAG, e.getMessage(), e);
- e.printStackTrace();
- }
- // This will only happen if there was an error getting or parsing the forecast.
- return null;
- }
- @Override
- protected void onPostExecute(String[] resultStr) {
- if(resultStr != null){
- mForecastAdapter.clear();
- for(String dayForecastStr : resultStr){
- mForecastAdapter.add(dayForecastStr);
- }
- //New data is back from server. Hooray!
- }
- }
- }
- }
- ##########################################
- pref_general.xml
- <?xml version="1.0" encoding="utf-8"?>
- <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <EditTextPreference
- android:title="@string/pref_location_label"
- android:key="@string/pref_location_key"
- android:defaultValue="@string/pref_location_default"
- android:inputType="text"
- android:singleLine="true" />
- <ListPreference
- android:title="@string/pref_units_label"
- android:key="@string/pref_units_key"
- android:defaultValue="@string/pref_units_metric"
- android:entryValues="@array/pref_units_values"
- android:entries="@array/pref_units_options" />
- </PreferenceScreen>
- ######################################
- THX IN ADVANCED
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement