转载请注明出处:
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中进行注册接收的广播
- public class UpdateTimeService extends Service {
- BroadcastReceiver mIntentReceiver = new BroadcastReceiver(){
- @Override
- public void onReceive(Context context, Intent intent) {
- if(Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())
- || Intent.ACTION_TIME_TICK.equals(intent.getAction())
- || Intent.ACTION_TIME_CHANGED.equals(intent.getAction()))
- WeatherWidgetProvider.UpdateTime(context);
-
- }
- };
-
- @Override
- public void onDestroy() {
- unregisterReceiver(mIntentReceiver);
- super.onDestroy();
- }
- @Override
- public void onCreate() {
- IntentFilter commandFilter = new IntentFilter();
- commandFilter.addAction(Intent.ACTION_TIME_TICK);
- commandFilter.addAction(Intent.ACTION_TIME_CHANGED);
- commandFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
- getBaseContext().registerReceiver(mIntentReceiver, commandFilter);
-
- super.onCreate();
- }
- @Override
- public void onStart(Intent intent, int startId) {
-
- super.onStart(intent, startId);
- }
- @Override
- public IBinder onBind(Intent arg0) {
-
- return null;
- }
- }
在WeatherWidgetProvider.java中提供静态方法public static void UpdateTime(Context context){。。。}刷新时间。
4.SAX解析,获取current_conditions节点内容
- public class XMLHandler extends DefaultHandler {
- private static final String TAG = "XMLHandler";
- private CurrentEntity currentWeather;
- private boolean currentFlag;
-
- public void setCurrentWeather(CurrentEntity currentWeather){
- this.currentWeather = currentWeather;
- }
- public CurrentEntity getCurrentWeather(){
- return currentWeather;
- }
-
- public XMLHandler() {
- currentFlag = false;
- }
-
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException {
-
- String tagName = localName.length() != 0 ? localName : qName;
- tagName = tagName.toLowerCase();
-
- Log.d(TAG,"tagName = "+tagName);
- if(tagName.equals("current_conditions")){
- currentFlag = true;
- currentWeather = new CurrentEntity();
- }
-
- if(currentFlag){
- if(tagName.equals("condition")){
- Log.d(TAG,"condition = "+attributes.getValue("data"));
- currentWeather.setCondition(attributes.getValue("data"));
- }else if(tagName.equals("temp_c")){
- Log.d(TAG,"temp_c--------");
- currentWeather.setTempc(attributes.getValue("data"));
- }else if(tagName.equals("humidity")){
- currentWeather.setHumidity(attributes.getValue("data"));
- }else if(tagName.equals("icon")){
- currentWeather.setIcon(attributes.getValue("data"));
- }else if(tagName.equals("wind_condition")){
- currentWeather.setWindcondition(attributes.getValue("data"));
- }
- }
-
-
- }
-
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- String tagName = localName.length() != 0 ? localName : qName;
- tagName = tagName.toLowerCase();
-
- if(tagName.equals("current_conditions")) {
- currentFlag = false;
- }
- }
- }
将节点对应的内容存放到CurrentEntity实体类中。
5.在天气的service中,开启线程,刷新小部件中的天气内容
- public class UpdateForecastService extends Service implements Runnable {
- private static final String TAG = "UpdateForecastService";
- private Uri currentUri = null;
- private String city = "Beijing";
- @Override
- public IBinder onBind(Intent arg0) {
-
- return null;
- }
- @Override
- public void onCreate() {
-
- super.onCreate();
- }
- @Override
- public void onDestroy() {
-
- super.onDestroy();
- }
- @Override
- public void onStart(Intent intent, int startId) {
- super.onStart(intent, startId);
-
- currentUri = intent.getData();
- Cursor cur = getContentResolver().query(currentUri, null, Weathers._ID +"="+ currentUri.getPathSegments().get(1), null, null);
-
- if(cur!=null && cur.getCount()>0){
- cur.moveToFirst();
- city = cur.getString(2);
- }
- Log.d(TAG,"-----------city = "+city);
-
- new Thread(this).start();
-
- }
-
- public void run(){
- Log.d(TAG,"----------------run --------------");
- SAXParserFactory spf = SAXParserFactory.newInstance();
-
- try {
- SAXParser sp = spf.newSAXParser();
- XMLReader reader = sp.getXMLReader();
-
- XMLHandler handler = new XMLHandler();
- reader.setContentHandler(handler);
-
- URL url = new URL(Weathers.WEB_URI + URLEncoder.encode(city));
- InputStream is = url.openStream();
- InputStreamReader isr = new InputStreamReader(is,"GBK");
- InputSource source = new InputSource(isr);
-
- reader.parse(source);
-
- CurrentEntity currentWeather = handler.getCurrentWeather();
- Log.d(TAG,"------tempc = "+currentWeather.getTempc()+" condition = "+currentWeather.getCondition());
-
- ContentValues values = new ContentValues();
- values.put(Weathers.CONDITION, currentWeather.getCondition());
- values.put(Weathers.TEMPC,currentWeather.getTempc());
- values.put(Weathers.HUMIDITY,currentWeather.getHumidity());
- values.put(Weathers.ICON,currentWeather.getIcon());
- values.put(Weathers.WINDCONDITION,currentWeather.getWindcondition());
-
- getContentResolver().update(currentUri, values, null, null);
-
- WeatherWidgetProvider.UpdateWeather(this,currentUri);
- } catch (Exception e) {
- e.printStackTrace();
- Log.d(TAG,"not complete the parser");
- }
-
-
- stopSelf();
- }
- }
6小部件对应appwidgetprovider
- public class WeatherWidgetProvider extends AppWidgetProvider{
- private static final String TAG = "WeatherWidgetProvider";
- private static int flagsDate = DateUtils.FORMAT_SHOW_DATE;
- private static int flagsWeek = DateUtils.FORMAT_SHOW_WEEKDAY;
-
- @Override
- public void onUpdate(Context context, AppWidgetManager appWidgetManager,
- int[] appWidgetIds) {
-
- UpdateTime(context);
- Intent intent=new Intent(context ,UpdateTimeService.class);
- context.startService(intent);
-
- for(int i=0;i<appWidgetIds.length;i++){
- Cursor cur = context.getContentResolver().query(Weathers.CONTENT_URI,null,Weathers.WIDGETID+"="+appWidgetIds[i],null,null);
- if(cur!=null&& cur.getCount()>0){
- cur.moveToFirst();
- String uri = Weathers.CONTENT_URI+"/"+String.valueOf(cur.getString(0));
- Intent intentForcast = new Intent(context,UpdateForecastService.class);
- intentForcast.setData(Uri.parse(uri));
- context.startService(intentForcast);
- }
- cur.close();
- }
-
- super.onUpdate(context, appWidgetManager, appWidgetIds);
- }
-
-
- @Override
- public void onDeleted(Context context, int[] appWidgetIds) {
- if(0 == appWidgetIds.length){
- Intent intent = new Intent(context ,UpdateTimeService.class);
- context.stopService(intent);
- }
- super.onDeleted(context, appWidgetIds);
- }
- private final static String M12 = "h:mm";
- private final static String M24 = "kk:mm";
- public static void UpdateTime(Context context){
- RemoteViews views=new RemoteViews(context.getPackageName(),R.layout.weather_appwidget);
- String dateStr = (String)DateUtils.formatDateTime(context, System.currentTimeMillis(), flagsDate);
- String smPmStr = DateUtils.getAMPMString(Calendar.getInstance().get(Calendar.AM_PM));
- String formatTime;
- if(android.text.format.DateFormat.is24HourFormat(context)){
- formatTime = M24;
- views.setViewVisibility(R.id.widget_am_pm,View.GONE);
- }else{
- formatTime = M12;
- views.setViewVisibility(R.id.widget_am_pm,View.VISIBLE);
- views.setTextViewText(R.id.widget_am_pm, smPmStr);
- }
- String timeStr = (String) DateFormat.format(formatTime,System.currentTimeMillis());
- String weekStr = (String)DateUtils.formatDateTime(context, System.currentTimeMillis(), flagsWeek);
-
- views.setTextViewText(R.id.widget_date,dateStr+" "+weekStr);
- views.setTextViewText(R.id.widget_time,timeStr);
-
- AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
- int[] appWidgetIds=appWidgetManager.getAppWidgetIds(new ComponentName(context, WeatherWidgetProvider.class));
- appWidgetManager.updateAppWidget(appWidgetIds, views);
- }
- public static void UpdateWeather(Context context, Uri currentUri) {
- Cursor curCurrent = context.getContentResolver().query(currentUri, null, Weathers._ID +"="+ currentUri.getPathSegments().get(1), null, null);
- if(curCurrent!=null && curCurrent.getCount()>0){
- curCurrent.moveToFirst();
-
- Log.d(TAG,"curCurrent.getInt(1) = "+curCurrent.getInt(1));
- Intent configIntent = new Intent(context, WeatherWidgetProvider.class);
- configIntent.setAction(currentUri.toString());
- configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,curCurrent.getInt(1));
- PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,configIntent, 0);
-
- RemoteViews views=new RemoteViews(context.getPackageName(),R.layout.weather_appwidget);
- views.setTextViewText(R.id.city,curCurrent.getString(2));
- views.setTextViewText(R.id.condition,curCurrent.getString(3));
- views.setTextViewText(R.id.tempc, curCurrent.getString(4)+"°");
- views.setTextViewText(R.id.humidity,curCurrent.getString(5));
- views.setImageViewResource(R.id.icon, WeatherUtil
- .getForecastImage(curCurrent.getString(6)));
-
- views.setOnClickPendingIntent(R.id.icon, pendingIntent);
-
- AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
- appWidgetManager.updateAppWidget(curCurrent.getInt(1), views);
- }
- curCurrent.close();
-
- }
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.d(TAG,"intent.getAction() = "+intent.getAction());
- if(intent.getAction().startsWith(Weathers.CONTENT_URI.toString())){
- int mAppWidgetId = intent.getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
- Uri uri = Uri.parse(intent.getAction());
- Log.d(TAG,"mAppWidgetId = "+mAppWidgetId+" uri = "+uri);
-
- Intent i = new Intent(context,UpdateForecastService.class);
- i.setData(uri);
- context.startService(i);
- }
-
-
- super.onReceive(context, intent);
- }
- }
在onUpdate中开启两个service,一个刷新时间,一个刷新天气。定义了一个Icon的点击事件,继续起到刷新天气的功能。
onReceive中接收点击事件,找到是哪一个小部件被点击了,根据小部件的Id进行区分。
当然此小部件是需要一个配置活动的,获取用户输入的城市名,不再多帖代码了,网上例子还是蛮多的
备注:搜狐天气api接口
http://sms.sohu.com/weatherfore/getformobile.php?city=北京