Android 开发一个天气预报桌面小部件

一 本片文章主要记录了如何开发一个桌面小部件,以及如何获取天气预报信息,并实时异步更新界面。

一个典型的桌面小部件开发步骤可以参考:http://www.cnblogs.com/playing/archive/2011/04/12/2013386.html

二 开发步骤

1.创建res/layout/weather_widget_layout.xml用以描述部件的布局,代码如下:


    
    
    
        
	    
	    
	        
	        
	    
    
    
 


2.创建一个小部件的内容提供者文件res/xml/weather_info.xml,代码如下:

  
 


3.创建一个AppWidgetProvider的子类WeatherWidget,代码如下:


public class WeatherWidget extends AppWidgetProvider {
	public static WeatherFm wf = new WeatherFm();

	@Override
	public void onUpdate(Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		super.onUpdate(context, appWidgetManager, appWidgetIds);
		Log.v("totoro","totoro1:" + appWidgetIds.length);
		LoadWeatherService.appWidgetIds = appWidgetIds;
		Log.v("totoro","totoro2:" + LoadWeatherService.appWidgetIds.length);
		context.startService(new Intent(context,LoadWeatherService.class));
	}
	
	public static RemoteViews updateRemoteViews(Context context) {
		RemoteViews view = new RemoteViews(context.getPackageName(),R.layout.weather_widget_layout);
		if (null == wf) {
			return null;
		} else {
			view.setTextViewText(R.id.cur_temp, wf.getCurTemperature());
			view.setTextViewText(R.id.low_temp, "低" + wf.getLowestTemperature());
			view.setTextViewText(R.id.high_temp, "高" + wf.getHighestTemperature());
			return view;
		}	
	}

}

关于类中的逻辑,稍后解释。

4. 在AndroidManifest.xml中注册:

 
			 
				 
			 
			 
 

以上是这个天气预报widget的基本创建步骤,而要实现天气的实时更新,还需要做更多的工作。


Android 开发一个天气预报桌面小部件_第1张图片     

这是这个桌面部件所要用到的所有类,由于涉及到网络访问,所以在WeatherWidget类的onReceive方法中,无法直接对UI进行更新。

context.startService(new Intent(context,LoadWeatherService.class));这句话是用以启动网络访问获取天气信息的服务,这个类代码如下:


 
   
public class LoadWeatherService extends Service implements Runnable{
	private static Object isLock = new Object();
	private static boolean isThreadRun = false;
	public static int[] appWidgetIds;

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.v("onStartCommand","totoro:" + intent.toString());
		new Thread(this).start();
//		synchronized (isLock) {
//			if (!isThreadRun) {
//				isThreadRun = true;
//				new Thread(this).start();
//			}
//		}
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void run() {
		Looper.prepare();
		Log.v("onStartCommand","totoro");
		
		BDLocationUtils utils = new BDLocationUtils(this.getApplicationContext());
		utils.requestBDLocation();
		
		AppWidgetManager manager = AppWidgetManager.getInstance(this);
		WeatherQueryImpl impl = new WeatherQueryImpl(this);
		WeatherWidget.wf = impl.weatherQuery(utils.cityCode);
		RemoteViews view = WeatherWidget.updateRemoteViews(this);
		if (null != view) {
			manager.updateAppWidget(appWidgetIds, view);
		} else {
			Log.e("run", "更新失败");
		}
		
		stopSelf();
		Looper.loop();
	}

}

 
   
 
   
 
  


在这个服务中,启动了一个线程去处理网络访问,获取天气信息并使用返回的数据,更新了UI,实际的天气预报获取操作,均在WeatherQueryImpl中实现:

public class WeatherQueryImpl implements WeatherQuery {
	private Context context;
	
	public WeatherQueryImpl(Context context) {
		this.context = context;
	}

	@Override
	public WeatherFm weatherQuery(String cityCode) {
		Log.v("weatherQuery","totoro:" + cityCode);
		String URL1 = "http://www.weather.com.cn/data/sk/" + cityCode + ".html";
		String URL2 = "http://www.weather.com.cn/data/cityinfo/" + cityCode + ".html";
		WeatherFm wf = new WeatherFm();
		wf.setCityCode(cityCode);
		String Weather_Result = "";
		HttpGet httpRequest = new HttpGet(URL1);
		// 获得当前温度
		try {
			HttpClient httpClient = new DefaultHttpClient();
			HttpResponse httpResponse = httpClient.execute(httpRequest);
			if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				// 取得返回的数据
				Weather_Result = EntityUtils.toString(httpResponse.getEntity());
				Log.v("totoro",Weather_Result);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		//以下是对返回JSON数据的解析
		if(null != Weather_Result&&!"".equals(Weather_Result)){
			try {
				JSONObject JO = new JSONObject(Weather_Result).getJSONObject("weatherinfo");
				wf.setCurTemperature(JO.getString("temp"));
				wf.setCityName(JO.getString("city"));
			} catch (JSONException e) {
				e.printStackTrace();
				return null;
			}
		}
		
		Weather_Result = "";
		httpRequest = new HttpGet(URL2);
		// 获得HttpResponse对象
		try {
			HttpClient httpClient = new DefaultHttpClient();
			HttpResponse httpResponse = httpClient.execute(httpRequest);
			if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				// 取得返回的数据
				Weather_Result = EntityUtils.toString(httpResponse.getEntity());
				Log.v("totoro",Weather_Result);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		//以下是对返回JSON数据的解析
		if(null != Weather_Result&&!"".equals(Weather_Result)){
			try {
				JSONObject JO = new JSONObject(Weather_Result).getJSONObject("weatherinfo");
				wf.setWeatherCondition(JO.getString("weather"));
				wf.setLowestTemperature(JO.getString("temp2"));
				wf.setHighestTemperature(JO.getString("temp1"));
			} catch (JSONException e) {
				e.printStackTrace();
				return null;
			}
		}
		return wf;
	}

	@Override
	public String cityQuery() {
		try {
			return LocationUtils.getCNByGPSlocation(context);
//			return LocationUtils.getCNByWIFILocation(context);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public WeatherFm getLocalWeather () {
		return weatherQuery(LocationCode.CHINESE_LOCAL_CODE.get(cityQuery()));
	}
}
 
   

 
   

关于天气预报的获取,来自中国天气网:http://www.weather.com.cn/,比较权威;此前共有3个接口可供使用:

http://m.weather.com.cn/data/101280601.html

http://www.weather.com.cn/data/sk/101280601.html 

http://www.weather.com.cn/data/cityinfo/101010100.html  

而第一个接口现在已经停止更新,第二个接口返回的数据格式如下:

"weatherinfo": {  
        "city": "深圳",  
        "cityid": "101280601",  
        "temp": "31",  
        "WD": "东南风",  
        "WS": "3级",  
        "SD": "58%",  
        "WSE": "3",  
        "time": "17:10",  
        "isRadar": "1",  
        "Radar": "JC_RADAR_AZ9755_JB"  
}  

第三个接口返回的数据格式如下:

"weatherinfo": {  
        "city": "深圳",  
        "cityid": "101280601",  
        "temp1": "26℃",  
        "temp2": "32℃",  
        "weather": "多云",  
        "img1": "n1.gif",  
        "img2": "d1.gif",  
        "ptime": "18:00"  
 }  


都是json格式,处理起来都很方便,而关于城市代码的获取,网上的资料很多。

location相关的类都是与城市定位有关系,由于还未实现完全,就不介绍了。



你可能感兴趣的:(Android)