android天气预报widget----google开源天气API,SAX解析

来源:互联网 发布:移动硬盘排名知乎 编辑:程序博客网 时间:2024/04/30 18:58


 

 

转载请注明出处:

http://blog.csdn.net/dany1202/archive/2011/05/17/6426064.aspx

 

1.知识基础:小部件、数据库、SAX解析XML文件

2.实现说明:

   google提供了天气预报的开放XML文件

   http://www.google.com/ig/api?hl=zh-cn&weather=Beijing

   查看如上网址,会看到界面显示一个XML文件,用SAX解析的方式获取XML文件节点内容,并将其存储到一个实体当中。

   存储数据到数据库。

   显示内容到小部件。

3.窗口小部件时间的实时刷新

   Intent.ACTION_TIME_CHANGED 为系统时间每次发生改变的时候,发送的广播,其只能动态注册

   所以在小部件的WeatherWidgetProvider.java中的onUpdate()方法中开启service,并在service中进行注册接收的广播

  

[java] view plaincopy
  1. public class UpdateTimeService extends Service {  
  2.     BroadcastReceiver mIntentReceiver = new BroadcastReceiver(){  
  3.         @Override  
  4.         public void onReceive(Context context, Intent intent) {  
  5.             if(Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())  
  6.                     || Intent.ACTION_TIME_TICK.equals(intent.getAction())  
  7.                     || Intent.ACTION_TIME_CHANGED.equals(intent.getAction()))  
  8.             WeatherWidgetProvider.UpdateTime(context);  
  9.               
  10.         }         
  11.     };  
  12.       
  13.     @Override  
  14.     public void onDestroy() {  
  15.         unregisterReceiver(mIntentReceiver);  
  16.         super.onDestroy();  
  17.     }  
  18.     @Override  
  19.     public void onCreate() {          
  20.         IntentFilter commandFilter = new IntentFilter();  
  21.         commandFilter.addAction(Intent.ACTION_TIME_TICK);  
  22.         commandFilter.addAction(Intent.ACTION_TIME_CHANGED);  
  23.         commandFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);  
  24.         getBaseContext().registerReceiver(mIntentReceiver, commandFilter);  
  25.           
  26.         super.onCreate();  
  27.     }  
  28.     @Override  
  29.     public void onStart(Intent intent, int startId) {  
  30.           
  31.         super.onStart(intent, startId);  
  32.     }  
  33.     @Override  
  34.     public IBinder onBind(Intent arg0) {  
  35.           
  36.         return null;  
  37.     }  
  38. }  

   在WeatherWidgetProvider.java中提供静态方法public static void UpdateTime(Context context){。。。}刷新时间。

4.SAX解析,获取current_conditions节点内容

  

[java] view plaincopy
  1. public class XMLHandler extends DefaultHandler {  
  2.     private static final String TAG = "XMLHandler";  
  3.     private CurrentEntity currentWeather;  
  4.     private boolean currentFlag;  
  5.       
  6.     public void setCurrentWeather(CurrentEntity currentWeather){  
  7.         this.currentWeather = currentWeather;  
  8.     }  
  9.     public CurrentEntity getCurrentWeather(){  
  10.         return currentWeather;  
  11.     }  
  12.     
  13.     public XMLHandler() {  
  14.         currentFlag = false;          
  15.     }  
  16.       
  17.     @Override  
  18.     public void startElement(String uri, String localName, String qName,  
  19.             Attributes attributes) throws SAXException {          
  20.           
  21.         String tagName = localName.length() != 0 ? localName : qName;  
  22.         tagName = tagName.toLowerCase();  
  23.          
  24.         Log.d(TAG,"tagName = "+tagName);  
  25.         if(tagName.equals("current_conditions")){  
  26.             currentFlag = true;  
  27.             currentWeather = new CurrentEntity();             
  28.         }  
  29.           
  30.         if(currentFlag){  
  31.             if(tagName.equals("condition")){  
  32.                 Log.d(TAG,"condition = "+attributes.getValue("data"));  
  33.                 currentWeather.setCondition(attributes.getValue("data"));  
  34.             }else if(tagName.equals("temp_c")){  
  35.                 Log.d(TAG,"temp_c--------");  
  36.                 currentWeather.setTempc(attributes.getValue("data"));  
  37.             }else if(tagName.equals("humidity")){  
  38.                 currentWeather.setHumidity(attributes.getValue("data"));  
  39.             }else if(tagName.equals("icon")){  
  40.                 currentWeather.setIcon(attributes.getValue("data"));  
  41.             }else if(tagName.equals("wind_condition")){  
  42.                 currentWeather.setWindcondition(attributes.getValue("data"));  
  43.             }  
  44.         }  
  45.           
  46.           
  47.     }  
  48.       
  49.     @Override  
  50.     public void endElement(String uri, String localName, String qName)  
  51.             throws SAXException {         
  52.         String tagName = localName.length() != 0 ? localName : qName;  
  53.         tagName = tagName.toLowerCase();  
  54.           
  55.         if(tagName.equals("current_conditions")) {            
  56.             currentFlag = false;             
  57.         }  
  58.     }  
  59. }  

  将节点对应的内容存放到CurrentEntity实体类中。

5.在天气的service中,开启线程,刷新小部件中的天气内容

  

[java] view plaincopy
  1. public class UpdateForecastService extends Service implements Runnable {  
  2.     private static final String TAG = "UpdateForecastService";  
  3.     private Uri currentUri = null;  
  4.     private String city = "Beijing";  
  5.     @Override  
  6.     public IBinder onBind(Intent arg0) {  
  7.         // TODO Auto-generated method stub  
  8.         return null;  
  9.     }  
  10.     @Override  
  11.     public void onCreate() {  
  12.           
  13.         super.onCreate();  
  14.     }  
  15.     @Override  
  16.     public void onDestroy() {  
  17.         // TODO Auto-generated method stub  
  18.         super.onDestroy();  
  19.     }  
  20.     @Override  
  21.     public void onStart(Intent intent, int startId) {  
  22.         super.onStart(intent, startId);  
  23.           
  24.         currentUri = intent.getData();        
  25.         Cursor cur = getContentResolver().query(currentUri, null, Weathers._ID +"="+ currentUri.getPathSegments().get(1), nullnull);  
  26.       
  27.         if(cur!=null && cur.getCount()>0){  
  28.             cur.moveToFirst();  
  29.             city = cur.getString(2);  
  30.         }         
  31.         Log.d(TAG,"-----------city = "+city);  
  32.           
  33.         new Thread(this).start();     
  34.           
  35.     }  
  36.       
  37.     public void run(){  
  38.         Log.d(TAG,"----------------run --------------");  
  39.         SAXParserFactory spf = SAXParserFactory.newInstance();  
  40.           
  41.         try {  
  42.             SAXParser sp = spf.newSAXParser();  
  43.             XMLReader reader = sp.getXMLReader();  
  44.               
  45.             XMLHandler  handler = new XMLHandler();  
  46.             reader.setContentHandler(handler);              
  47.       
  48.             URL url = new URL(Weathers.WEB_URI + URLEncoder.encode(city));  
  49.             InputStream is = url.openStream();  
  50.             InputStreamReader isr = new InputStreamReader(is,"GBK");  
  51.             InputSource source = new InputSource(isr);  
  52.       
  53.             reader.parse(source);  
  54.               
  55.             CurrentEntity currentWeather = handler.getCurrentWeather();  
  56.             Log.d(TAG,"------tempc = "+currentWeather.getTempc()+"    condition = "+currentWeather.getCondition());  
  57.               
  58.             ContentValues values = new ContentValues();             
  59.             values.put(Weathers.CONDITION, currentWeather.getCondition());  
  60.             values.put(Weathers.TEMPC,currentWeather.getTempc());  
  61.             values.put(Weathers.HUMIDITY,currentWeather.getHumidity());  
  62.             values.put(Weathers.ICON,currentWeather.getIcon());  
  63.             values.put(Weathers.WINDCONDITION,currentWeather.getWindcondition());  
  64.               
  65.             getContentResolver().update(currentUri, values, nullnull);  
  66.               
  67.             WeatherWidgetProvider.UpdateWeather(this,currentUri);  
  68.         } catch (Exception e) {  
  69.             e.printStackTrace();  
  70.             Log.d(TAG,"not complete the parser");  
  71.         }  
  72.           
  73.           
  74.         stopSelf();  
  75.     }  
  76. }  

6小部件对应appwidgetprovider

[java] view plaincopy
  1. public class WeatherWidgetProvider extends AppWidgetProvider{  
  2.     private static final String TAG = "WeatherWidgetProvider";  
  3.     private static int flagsDate = DateUtils.FORMAT_SHOW_DATE;    
  4.     private static int flagsWeek = DateUtils.FORMAT_SHOW_WEEKDAY;  
  5.       
  6.     @Override  
  7.     public void onUpdate(Context context, AppWidgetManager appWidgetManager,  
  8.             int[] appWidgetIds) {  
  9.           
  10.         UpdateTime(context);      
  11.         Intent intent=new Intent(context ,UpdateTimeService.class);   
  12.         context.startService(intent);             
  13.           
  14.         for(int i=0;i<appWidgetIds.length;i++){  
  15.             Cursor cur = context.getContentResolver().query(Weathers.CONTENT_URI,null,Weathers.WIDGETID+"="+appWidgetIds[i],null,null);  
  16.             if(cur!=null&& cur.getCount()>0){  
  17.                 cur.moveToFirst();  
  18.                 String uri = Weathers.CONTENT_URI+"/"+String.valueOf(cur.getString(0));  
  19.             Intent intentForcast = new Intent(context,UpdateForecastService.class);  
  20.             intentForcast.setData(Uri.parse(uri));  
  21.             context.startService(intentForcast);  
  22.             }  
  23.             cur.close();  
  24.         }  
  25.                           
  26.         super.onUpdate(context, appWidgetManager, appWidgetIds);  
  27.     }  
  28.       
  29.       
  30.     @Override  
  31.     public void onDeleted(Context context, int[] appWidgetIds) {  
  32.         if(0 == appWidgetIds.length){  
  33.             Intent intent = new Intent(context ,UpdateTimeService.class);  
  34.             context.stopService(intent);  
  35.         }         
  36.         super.onDeleted(context, appWidgetIds);  
  37.     }  
  38.     private final static String M12 = "h:mm";  
  39.     private final static String M24 = "kk:mm";  
  40.     public static void UpdateTime(Context context){  
  41.         RemoteViews views=new RemoteViews(context.getPackageName(),R.layout.weather_appwidget);  
  42.         String dateStr = (String)DateUtils.formatDateTime(context, System.currentTimeMillis(), flagsDate);  
  43.         String smPmStr = DateUtils.getAMPMString(Calendar.getInstance().get(Calendar.AM_PM));  
  44.         String formatTime;  
  45.         if(android.text.format.DateFormat.is24HourFormat(context)){  
  46.             formatTime = M24;  
  47.             views.setViewVisibility(R.id.widget_am_pm,View.GONE);             
  48.         }else{  
  49.             formatTime = M12;  
  50.             views.setViewVisibility(R.id.widget_am_pm,View.VISIBLE);  
  51.             views.setTextViewText(R.id.widget_am_pm, smPmStr);  
  52.         }  
  53.         String timeStr = (String) DateFormat.format(formatTime,System.currentTimeMillis());  
  54.         String weekStr = (String)DateUtils.formatDateTime(context, System.currentTimeMillis(), flagsWeek);  
  55.           
  56.         views.setTextViewText(R.id.widget_date,dateStr+" "+weekStr);  
  57.         views.setTextViewText(R.id.widget_time,timeStr);  
  58.           
  59.         AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);  
  60.         int[] appWidgetIds=appWidgetManager.getAppWidgetIds(new  ComponentName(context, WeatherWidgetProvider.class));  
  61.         appWidgetManager.updateAppWidget(appWidgetIds, views);  
  62.     }  
  63.     public static void UpdateWeather(Context context, Uri currentUri) {  
  64.         Cursor curCurrent = context.getContentResolver().query(currentUri, null, Weathers._ID +"="+ currentUri.getPathSegments().get(1), nullnull);  
  65.         if(curCurrent!=null && curCurrent.getCount()>0){  
  66.             curCurrent.moveToFirst();  
  67.               
  68.             Log.d(TAG,"curCurrent.getInt(1) = "+curCurrent.getInt(1));  
  69.             Intent configIntent = new Intent(context, WeatherWidgetProvider.class);  
  70.             configIntent.setAction(currentUri.toString());                
  71.             configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,curCurrent.getInt(1));  
  72.             PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,configIntent, 0);  
  73.               
  74.             RemoteViews views=new RemoteViews(context.getPackageName(),R.layout.weather_appwidget);  
  75.             views.setTextViewText(R.id.city,curCurrent.getString(2));  
  76.             views.setTextViewText(R.id.condition,curCurrent.getString(3));  
  77.             views.setTextViewText(R.id.tempc, curCurrent.getString(4)+"°");  
  78.             views.setTextViewText(R.id.humidity,curCurrent.getString(5));  
  79.             views.setImageViewResource(R.id.icon, WeatherUtil  
  80.                     .getForecastImage(curCurrent.getString(6)));  
  81.               
  82.             views.setOnClickPendingIntent(R.id.icon, pendingIntent);  
  83.               
  84.             AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);  
  85.             appWidgetManager.updateAppWidget(curCurrent.getInt(1), views);  
  86.         }  
  87.         curCurrent.close();  
  88.           
  89.     }  
  90.     @Override  
  91.     public void onReceive(Context context, Intent intent) {       
  92.         Log.d(TAG,"intent.getAction() = "+intent.getAction());  
  93.         if(intent.getAction().startsWith(Weathers.CONTENT_URI.toString())){  
  94.             int mAppWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);  
  95.             Uri uri = Uri.parse(intent.getAction());  
  96.             Log.d(TAG,"mAppWidgetId = "+mAppWidgetId+"    uri = "+uri);  
  97.               
  98.             Intent i = new Intent(context,UpdateForecastService.class);  
  99.             i.setData(uri);  
  100.             context.startService(i);  
  101.         }  
  102.           
  103.           
  104.         super.onReceive(context, intent);  
  105.     }  
  106. }   

 

在onUpdate中开启两个service,一个刷新时间,一个刷新天气。定义了一个Icon的点击事件,继续起到刷新天气的功能。

onReceive中接收点击事件,找到是哪一个小部件被点击了,根据小部件的Id进行区分。

当然此小部件是需要一个配置活动的,获取用户输入的城市名,不再多帖代码了,网上例子还是蛮多的

备注:搜狐天气api接口

http://sms.sohu.com/weatherfore/getformobile.php?city=北京

原创粉丝点击