WeatherWidget.java :  » Widget » wetherwidget » de » sdw » android » weather » widget » Android Open Source

Android Open Source » Widget » wetherwidget 
wetherwidget » de » sdw » android » weather » widget » WeatherWidget.java
package de.sdw.android.weather.widget;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;

import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.text.Html;
import android.util.Log;
import android.widget.RemoteViews;
import de.sdw.android.weather.R;

public class WeatherWidget extends AppWidgetProvider {
  
  private static final String PLZS_FILENAME = "plzs.store";
  public static final String TAG_WEATHER = "weather";
  public static final String EXTRA_PLZ = "PLZ";
  private static final String URL_WETTERONLINE = "http://m.wetteronline.de/cgi-bin/city?L=dep";
  private static final String URL_PLZ = "54294";      
  private static final String EXTRA_WIDGET_IDS = "EXTRA_WIDGET_IDS";
  
  private static RemoteViews views;
  
  private static HashMap<Integer, Integer> plzs;
  
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // To prevent any ANR timeouts, we perform the update in a service
      Log.d(TAG_WEATHER, "PLZs: " + getPLZs());
      ctx = context;
      WeatherWidget.updateView(context, appWidgetIds);
    }
   
    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
      super.onDeleted(context, appWidgetIds);
      ctx = context;
      for (int i = 0; i <= appWidgetIds.length; i++) {
        Log.d(TAG_WEATHER, "Delete the plz(" + getPLZs().get(appWidgetIds[i]) 
            + ") for the following widget: " + appWidgetIds[i]);
        getPLZs().remove(appWidgetIds[i]);
      }
      savePlZsToFile();        
    }
    
    private static Context ctx;
    
    /**
     * Method to tricker an update of the view for all given appWidgetIds.
     * 
     * @param context
     * @param appWidgetIds
     */
    public static void updateView(Context context, int[] appWidgetIds) {
      Intent intent = new Intent(context, UpdateService.class);
      intent.putExtra(EXTRA_WIDGET_IDS, appWidgetIds);     
      context.startService(intent);
    }
    
    public static void setPLZ(Context context, int widgetId, int plz) {
      ctx = context;
      Log.d(TAG_WEATHER, "Adding PLZ(" + plz + ") for the following widget: " + widgetId);
      getPLZs().put(widgetId, plz);
      savePlZsToFile();
    }
    
    private static void savePlZsToFile() {
      FileOutputStream fos = null;
      
      try {
      fos = ctx.openFileOutput(PLZS_FILENAME, Context.MODE_PRIVATE);
      ObjectOutputStream oos = new ObjectOutputStream(fos);
      oos.writeObject(getPLZs());
      oos.close();
    } catch (Exception e) {
      Log.e(TAG_WEATHER, "could not write plzs to settingsfile", e);
    } finally {
      if (fos != null) {
        try {
          fos.close();
        } catch (IOException e) { /* I don't care! */}
      }
    }
  }

  private static HashMap<Integer, Integer> getPLZs() {
      if (plzs == null) {
        plzs = readPLZsFromFile();
      }
      return plzs;
    }
    
  /**
   * Open the 
   * 
   * @return
   */
    @SuppressWarnings("unchecked")
  private static HashMap<Integer, Integer> readPLZsFromFile() {
      FileInputStream fis = null;
      try {
        if (ctx == null) {
          Log.d(TAG_WEATHER, "Context is null!");
          return null;
        }
      fis = ctx.openFileInput(PLZS_FILENAME);
      ObjectInputStream ois = new ObjectInputStream(fis);
      Object obj = ois.readObject();
      
      if (obj != null) {
        if (obj instanceof HashMap) {
          plzs = (HashMap<Integer, Integer>) obj;
          Log.d(TAG_WEATHER, "PLZs contained in settings file." + plzs);
        } else {
          Log.e(TAG_WEATHER, "Unexpected object stored in settings-file.");
        }
      } else {
        Log.d(TAG_WEATHER, "No PLZs in settings found.");
        plzs = new HashMap<Integer, Integer>();
      }
      ois.close();
    } catch (Exception e) {
      Log.e(TAG_WEATHER, "Failed to read PLZs from settingsfile", e);
    } finally {
      if (fis != null) {
        try {
          fis.close();
        } catch (IOException e) { /* I don't care! */}
      }
    }
    return plzs;
  }

  public static class UpdateService extends Service {
      
    private static final String TABLE_ENTRIES_XPATH = "/body/div[@class='board']/div[@class='content']/table//tr";
      private static final String DAY_XPATH = "/body/div[@class='board']/div[@class='content']/div[@class='city']";
      private static final String FORECAST_XPATH = "/td[3]";
      private static final String FORECAST_TEMP_XPATH = "/td[2]";
      private static final String URL_DAY1 = "00";
      private static final String URL_DAY2 = "01";
      private static final String URL_DAY3 = "02";      
      private String combinedUrl = URL_WETTERONLINE + URL_PLZ;
      
      
        public class Day {
          String title = new String();
          String min = new String();
          String max = new String();
          String morning = new String();
          String midday = new String();
          String evening = new String();
        }
      
    @Override
    public IBinder onBind(Intent arg0) {
      return null;
    }
    
    @Override
    public void onStart(Intent intent, int startId) {
      int[] intArray = intent.getIntArrayExtra(EXTRA_WIDGET_IDS);
      Log.d(TAG_WEATHER, "Service for updating the widgets started.");
      for (int i = 0; i < intArray.length; i++) {
        if (intArray.length < 1 || getPLZs().get(intArray[i]) == null) {
          return;
        } else {          
          int plz = getPLZs().get(intArray[i]);
          combinedUrl = URL_WETTERONLINE + plz;
          Log.d(TAG_WEATHER, "The URL for widget(" + intArray[i] + "): " + combinedUrl);
          RemoteViews updateViews = buildUpdate(this, intent);
          AppWidgetManager manager = AppWidgetManager.getInstance(this);
          manager.updateAppWidget(intArray[i], updateViews);
        }
      }
    }
    
    public RemoteViews buildUpdate(Context context, Intent intent) {
      
      views = new RemoteViews(context.getPackageName(), R.layout.widget);
      try {
        extractCleaner();
      } catch (Throwable e) {
        Log.e(TAG_WEATHER, "failure during extraction", e);
      }
      
      PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
      views.setOnClickPendingIntent(R.layout.widget_config, pendingIntent);
      return views;
    }
    
    private void extractCleaner() throws IOException, XPatherException {
      fillDayOne(getForecast(new URL(combinedUrl + URL_DAY1)));
      fillDayTwo(getForecast(new URL(combinedUrl + URL_DAY2)));
      fillDayThree(getForecast(new URL(combinedUrl + URL_DAY3)));
      views.setTextViewText(R.id.Status, "Stand: " +  new Date().toLocaleString());
    }

    private Day getForecast(URL url) throws IOException, XPatherException {
      HtmlCleaner cleaner = getHtmlCleaner();
      Log.d(TAG_WEATHER, "Get forecast from url: /n" + url.toString());
      TagNode node = cleaner.clean(url.openStream());
      Log.d(TAG_WEATHER, "cleanedString: " +  node);
      Object[] objRows = node.evaluateXPath(TABLE_ENTRIES_XPATH);
      ArrayList<TagNode> rows = new ArrayList<TagNode>();
      for (Object obj : objRows) {
        if(obj instanceof TagNode) {
          rows.add((TagNode) obj);
        }
      }
      Log.d(TAG_WEATHER, "rows: " + rows.size());
      Day day = new Day();
      fillDayForecast(day, rows);
      fillDayName(day, node);
      return day;
    }
    
    private HtmlCleaner getHtmlCleaner() {
      HtmlCleaner cleaner = new HtmlCleaner();
      CleanerProperties props = cleaner.getProperties();
      props.setAllowHtmlInsideAttributes(true);
      props.setAllowMultiWordAttributes(true);
      props.setRecognizeUnicodeChars(true);
      props.setOmitComments(true);
      props.setPruneTags("img");
      return cleaner;
    }
    
    
    void fillDayForecast(Day day, List<TagNode> rows) {
      try {
        day.min = extractTemperature(rows.get(0));
        day.max = extractTemperature(rows.get(1));
        day.morning = extractForecast(rows.get(2));
        day.midday = extractForecast(rows.get(3));
        day.evening = extractForecast(rows.get(4));
      } catch (XPatherException e) {
        Log.e(TAG_WEATHER, "Couldn't map the http result to day information", e);
      }
    }
    
    public void fillDayName(Day day, TagNode node) throws XPatherException {
      String dayName = ((TagNode) node.evaluateXPath(DAY_XPATH)[0]).getText().toString();
      day.title = cleanUpName(dayName);
    }
    
    String cleanUpName(String text) {
      text = text.substring(20, text.indexOf(","));
      return text;
    }
    
    public String extractTemperature(TagNode row) throws XPatherException {
      TagNode contentColumn = (TagNode) row.evaluateXPath(FORECAST_TEMP_XPATH)[0];
      String encodedText = contentColumn.getText().toString().trim();
      return Html.fromHtml(encodedText).toString();
    }
    
    public String extractForecast(TagNode row) throws XPatherException {
      TagNode contentColumn = (TagNode) row.evaluateXPath(FORECAST_XPATH)[0];
      String encodedText = contentColumn.getText().toString().trim();
      return Html.fromHtml(encodedText).toString();
    }
    
    private void fillDayOne(Day day) {
      views.setTextViewText(R.id.Header1, day.title);
      views.setTextViewText(R.id.Temperature1Min, day.min);
      views.setTextViewText(R.id.Temperature1Max, day.max);
      views.setTextViewText(R.id.Morning1, day.morning);
      views.setTextViewText(R.id.Midday1, day.midday);
      views.setTextViewText(R.id.Evening1, day.evening);
    }
    
    private void fillDayTwo(Day day) {
      views.setTextViewText(R.id.Header2, day.title);
      views.setTextViewText(R.id.Temperature2Min, day.min);
      views.setTextViewText(R.id.Temperature2Max, day.max);
      views.setTextViewText(R.id.Morning2, day.morning);
      views.setTextViewText(R.id.Midday2, day.midday);
      views.setTextViewText(R.id.Evening2, day.evening);
      
    }
    
    private void fillDayThree(Day day) {
      views.setTextViewText(R.id.Header3, day.title);
      views.setTextViewText(R.id.Temperature3Min, day.min);
      views.setTextViewText(R.id.Temperature3Max, day.max);
      views.setTextViewText(R.id.Morning3, day.morning);
      views.setTextViewText(R.id.Midday3, day.midday);
      views.setTextViewText(R.id.Evening3, day.evening);
    }
  
    }
    
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.