您的位置:首页 > 移动开发 > Android开发

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

2011-12-15 09:41 399 查看
最近项目不太忙,就抽空看了看天气预报,做个玩玩,上图:



转载请注明出处:



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中进行注册接收的广播

view
plain

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节点内容

view
plain

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中,开启线程,刷新小部件中的天气内容

view
plain

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) {

// TODO Auto-generated method stub

return null;

}

@Override

public void onCreate() {

super.onCreate();

}

@Override

public void onDestroy() {

// TODO Auto-generated method stub

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

view
plain

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=北京
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐