public static List<WidgetRow> getDesiredWidgetsFromPrefs(Context context) {

    String[] rows = MetaWatchService.getWidgets(context).split("\\|");

    List<WidgetRow> result = new ArrayList<WidgetRow>();

    for (String line : rows) {
      WidgetRow row = new WidgetRow();
      String[] widgets = line.split(",");
      for (String widget : widgets) {
        row.add(widget);
      }
      result.add(row);
    }

    return result;
  }
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {

          if (Preferences.logging) Log.d(MetaWatch.TAG, "onSharedPreferenceChanged " + key);

          MetaWatchService.loadPreferences(context);

          if (key.contains("Weather")) {
            Monitors.restart(context);
          }

          if (key.contains("Idle") || key.contains(".app_enabled")) {
            Idle.reset(context);
          }

          if (key.contains("Widgets") || (key.equals("SilentMode"))) {
            Idle.updateIdle(context, true);
          }
        }
  public synchronized WeatherData update(Context context, WeatherData weatherData) {
    try {
      if (isUpdateRequired(weatherData)) {
        if (Preferences.logging) Log.d(MetaWatch.TAG, "Monitors.updateWeatherDataGoogle(): start");

        String queryString;
        if (isGeolocationDataUsed()) {
          GoogleGeoCoderLocationData locationData =
              reverseLookupGeoLocation(context, LocationData.latitude, LocationData.longitude);
          weatherData.locationName = locationData.getLocationName();
          long lat = (long) (LocationData.latitude * 1000000);
          long lon = (long) (LocationData.longitude * 1000000);
          queryString = "http://www.google.com/ig/api?weather=,,," + lat + "," + lon;
        } else {
          String weatherLocation =
              Preferences.weatherCity.replace(",", " ").replace("  ", " ").replace(" ", "%20");
          queryString = "http://www.google.com/ig/api?weather=" + weatherLocation;
          weatherData.locationName = Preferences.weatherCity;
        }

        HttpClient hc = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(queryString);
        HttpResponse rp = hc.execute(httpGet);

        if (rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
          String s = EntityUtils.toString(rp.getEntity());
          if (Preferences.logging) Log.d(MetaWatch.TAG, "Got weather data " + s);

          SAXParserFactory spf = SAXParserFactory.newInstance();
          SAXParser sp = spf.newSAXParser();
          XMLReader xr = sp.getXMLReader();

          GoogleWeatherHandler gwh = new GoogleWeatherHandler();
          xr.setContentHandler(gwh);
          xr.parse(new InputSource(new StringReader(s)));
          WeatherSet ws = gwh.getWeatherSet();
          if (ws == null || ws.getWeatherCurrentCondition() == null) {
            if (Preferences.logging)
              Log.e(MetaWatch.TAG, "Google Weather API did not respond with valid data: " + s);
          } else {
            WeatherCurrentCondition wcc = ws.getWeatherCurrentCondition();

            ArrayList<WeatherForecastCondition> conditions = ws.getWeatherForecastConditions();

            int days = conditions.size();
            weatherData.forecast = new Forecast[days];

            for (int i = 0; i < days; ++i) {
              WeatherForecastCondition wfc = conditions.get(i);

              weatherData.forecast[i] = new Forecast();
              weatherData.forecast[i].setDay(wfc.getDayofWeek());
              weatherData.forecast[i].setIcon(getIcon(wfc.getCondition().toLowerCase()));

              if (Preferences.weatherCelsius) {
                weatherData.forecast[i].setTempHigh(wfc.getTempMaxCelsius());
                weatherData.forecast[i].setTempLow(wfc.getTempMinCelsius());
              } else {
                weatherData.forecast[i].setTempHigh(
                    WeatherUtils.celsiusToFahrenheit(wfc.getTempMaxCelsius()));
                weatherData.forecast[i].setTempLow(
                    WeatherUtils.celsiusToFahrenheit(wfc.getTempMinCelsius()));
              }

              if (Preferences.logging)
                Log.d(MetaWatch.TAG, "Forecast #" + i + ": " + weatherData.forecast[i]);
            }

            weatherData.celsius = Preferences.weatherCelsius;

            String cond = wcc.getCondition();
            weatherData.condition = cond;

            if (Preferences.weatherCelsius) {
              weatherData.temp = Integer.toString(wcc.getTempCelcius());
            } else {
              weatherData.temp = Integer.toString(wcc.getTempFahrenheit());
            }

            cond = cond.toLowerCase();

            weatherData.icon = getIcon(cond);
            weatherData.received = true;
            weatherData.timeStamp = System.currentTimeMillis();

            Idle.updateIdle(context, true);
            MetaWatchService.notifyClients();
          }
        }
      }

    } catch (Exception e) {
      if (Preferences.logging) Log.e(MetaWatch.TAG, "Exception while retreiving weather", e);
    } finally {
      if (Preferences.logging) Log.d(MetaWatch.TAG, "Monitors.updateWeatherData(): finish");
    }

    return weatherData;
  }
  void pressedButton(int button) {
    if (Preferences.logging) Log.d(MetaWatch.TAG, "button code: " + Integer.toString(button));

    wakeLock.acquire(10000);

    try {

      if (button > 0 && Preferences.hapticFeedback) Protocol.vibrate(5, 5, 2);

      if (Preferences.logging)
        Log.d(MetaWatch.TAG, "MetaWatchService.pressedButton(): watchState=" + watchState);
      switch (watchState) {
        case WatchStates.IDLE:
          {
            int idleAppButton = Idle.appButtonPressed(this, button);
            if (idleAppButton == ApplicationBase.BUTTON_NOT_USED) {

              switch (button) {
                case Idle.QUICK_BUTTON:
                  Idle.quickButtonAction(this);
                  break;

                case Idle.IDLE_NEXT_PAGE:
                  if (MetaWatchService.watchType == MetaWatchService.WatchType.DIGITAL) {
                    Idle.nextPage(this);
                    Idle.updateIdle(this, true);
                  }
                  break;

                case Idle.TOGGLE_SILENT:
                  MetaWatchService.setSilentMode(!silentMode);
                  Protocol.vibrate(500, 500, 2);
                  break;

                case Idle.IDLE_OLED_DISPLAY:
                  long time = System.currentTimeMillis();

                  if (time - lastOledCrownPress < 1000 * 5) {
                    Idle.nextPage(this);
                    Idle.updateIdle(this, true);
                  }

                  lastOledCrownPress = time;
                  Idle.sendOledIdle(this);
                  break;

                case Application.TOGGLE_APP:
                  Application.toggleApp(context, Idle.getCurrentApp());
                  break;
              }
            } else if (idleAppButton != ApplicationBase.BUTTON_USED_DONT_UPDATE) {
              Idle.updateIdle(this, false);
              if (MetaWatchService.watchType == MetaWatchService.WatchType.ANALOG)
                Idle.sendOledIdle(this);
            }
            break;
          }

        case WatchStates.APPLICATION:
          Application.buttonPressed(this, button);
          break;

        case WatchStates.NOTIFICATION:
          switch (button) {
            case Call.CALL_ANSWER:
              MediaControl.answerCall(this);
              break;
            case Call.CALL_DISMISS:
              MediaControl.ignoreCall(this);
              break;
            case Call.CALL_MENU:
              ActionManager.displayCallActions(this);
              break;
            default:
              Notification.buttonPressed(button);
              break;
          }
          break;
      }

    } finally {
      if (wakeLock != null && wakeLock.isHeld()) {
        wakeLock.release();
      }
    }
  }