項目要求在應用首頁面展示本地當日天氣的概況,首先想到的是google和雅虎,前者很久之前接觸過,聽說後來用不了了,後者由於郵箱事件的緣故個人不喜歡(雖然貌似蘋果也用雅虎的天氣預報),之後又想到了前段時間寫的調用webservice的例子,可是頻繁的在手機調用畢竟不太放心,加之免費版的各種限制,還是放棄了!搜了很多資料,也問了群裡的一些人士,最後決定使用"中國天氣網"來實現http://www.weather.com.cn/,在國內這個算是比較權威了吧,下面印著"中國氣象局公共氣象服務中心"的版權呢!通過接口返回的數據信息量很大,也比較穩定,絕對可以滿足一般應用對天氣的需求!就是有一點比較麻煩,需要知道對應的城市碼,稍後說明我的處理辦法!
沒有官方的API,都是網絡上大家研究貢獻的成果,普遍流傳的有這麼三個接口(以深圳的城市代碼101280601為例):
①http://m.weather.com.cn/data/101280601.html 返回的信息最全的接口
[html]
<span style="font-family:Comic Sans MS; font-size:18px">{
"weatherinfo": {
"city": "深圳",
"city_en": "shenzhen",
"date_y": "2013年9月11日",
"date": "",
"week": "星期三",
"fchh": "11",
"cityid": "101280601",
"temp1": "33℃~27℃",
"temp2": "32℃~26℃",
"temp3": "28℃~25℃",
"temp4": "29℃~25℃",
"temp5": "30℃~25℃",
"temp6": "31℃~26℃",
"tempF1": "91.4℉~80.6℉",
"tempF2": "89.6℉~78.8℉",
"tempF3": "82.4℉~77℉",
"tempF4": "84.2℉~77℉",
"tempF5": "86℉~77℉",
"tempF6": "87.8℉~78.8℉",
"weather1": "多雲",
"weather2": "陣雨",
"weather3": "陣雨",
"weather4": "陣雨",
"weather5": "陣雨",
"weather6": "陣雨",
"img1": "1",
"img2": "99",
"img3": "3",
"img4": "99",
"img5": "3",
"img6": "99",
"img7": "3",
"img8": "99",
"img9": "3",
"img10": "99",
"img11": "3",
"img12": "99",
"img_single": "1",
"img_title1": "多雲",
"img_title2": "多雲",
"img_title3": "陣雨",
"img_title4": "陣雨",
"img_title5": "陣雨",
"img_title6": "陣雨",
"img_title7": "陣雨",
"img_title8": "陣雨",
"img_title9": "陣雨",
"img_title10": "陣雨",
"img_title11": "陣雨",
"img_title12": "陣雨",
"img_title_single": "多雲",
"wind1": "微風",
"wind2": "微風",
"wind3": "微風",
"wind4": "微風",
"wind5": "微風",
"wind6": "微風",
"fx1": "微風",
"fx2": "微風",
"fl1": "小於3級",
"fl2": "小於3級",
"fl3": "小於3級",
"fl4": "小於3級",
"fl5": "小於3級",
"fl6": "小於3級",
"index": "炎熱",
"index_d": "天氣炎熱,建議著短衫、短裙、短褲、薄型T恤衫等清涼夏季服裝。",
"index48": "炎熱",
"index48_d": "天氣炎熱,建議著短衫、短裙、短褲、薄型T恤衫等清涼夏季服裝。",
"index_uv": "中等",
"index48_uv": "中等",
"index_xc": "不宜",
"index_tr": "較適宜",
"index_co": "較不舒適",
"st1": "33",
"st2": "26",
"st3": "30",
"st4": "24",
"st5": "25",
"st6": "23",
"index_cl": "較適宜",
"index_ls": "適宜",
"index_ag": "不易發"
}
}</span>
②http://www.weather.com.cn/data/sk/101280601.html 返回的信息比較簡潔
[html]
<span style="font-family:Comic Sans MS; font-size:18px">{
"weatherinfo": {
"city": "深圳",
"cityid": "101280601",
"temp": "31",
"WD": "東南風",
"WS": "3級",
"SD": "58%",
"WSE": "3",
"time": "17:10",
"isRadar": "1",
"Radar": "JC_RADAR_AZ9755_JB"
}
}</span>
③http://www.weather.com.cn/data/cityinfo/101010100.html 另一個返回信息簡潔的接口
[html]
<span style="font-family:Comic Sans MS; font-size:18px">{
"weatherinfo": {
"city": "深圳",
"cityid": "101280601",
"temp1": "26℃",
"temp2": "32℃",
"weather": "多雲",
"img1": "n1.gif",
"img2": "d1.gif",
"ptime": "18:00"
}
}</span>
返回的數據是json格式的,處理起來並不麻煩,可是城市代碼怎麼辦?一種方法是打開中國天氣網的官網,在查詢框中輸入你所要查詢的城市,浏覽器跳轉到的頁面會顯示一個地址,比如:http://www.weather.com.cn/weather/101280601.shtml,那麼紅色的部分就是你所查詢的城市對應的城市代碼!可是這也太有局限性了吧!
還有的文章介紹根據IP地址獲取城市代碼,但應該不適用在Android移動端吧,我沒有研究,所有采用了下面的辦法:第二種是將最新的城市代碼放入本地數據庫(數據庫文件我放在末尾處,需要的可以下載,在中國范圍內應該足夠用了),通過在代碼中查詢城市名稱從數據庫中取出與之對應的城市代碼,通過字符串的拼接發送請求,來獲取想要的天氣信息!這個是我自己的思路,或許比較笨拙,希望有更好想法的朋友可以指出!
下面的這段代碼是根據城市名稱從本地數據庫中查詢出與之對應的城市代碼,通過封裝的HttpGet方法來獲取返回的數據,並使用json解析出自己所需要的內容:
[java]
<span style="font-family:Comic Sans MS; font-size:18px">public void initWaetherData() {
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
DBHelper helper = new DBHelper(getApplicationContext());
String cityName = "深圳";
String cityCode = null;
String sql = "select * from city_table where CITY =" + "'"
+ cityName + "'" + ";";
Log.i("TAG", "sql:" + sql);
Cursor cursor = helper.getReadableDatabase()
.rawQuery(sql, null);
if (cursor != null) {
cursor.moveToFirst();
cityCode = cursor.getString(cursor
.getColumnIndex("WEATHER_ID"));
Log.i("TAG", "cityCode:" + cityCode);
}
cursor.close();
helper.close();
String weatherUrl = "http://www.weather.com.cn/data/cityinfo/" + cityCode
+ ".html";
String weatherJson = queryStringForGet(weatherUrl);
Log.i("TAG", weatherJson);
try {
JSONObject jsonObject = new JSONObject(weatherJson);
JSONObject weatherObject = jsonObject
.getJSONObject("weatherinfo");
Log.i("TAG", "city:" + weatherObject.getString("city"));
Log.i("TAG", "temp:" + weatherObject.getString("temp1"));
Log.i("TAG", "temp:" + weatherObject.getString("temp2"));
Log.i("TAG","weather:" + weatherObject.getString("weather"));
Log.i("TAG", "temp:" + weatherObject.getString("img1"));
Log.i("TAG", "temp:" + weatherObject.getString("img2"));
Message message = new Message();
message.obj = weatherObject;
handler.sendMessage(message);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}</span>
在handler中根據需要將返回的內容解析並顯示到界面:
[java]
<span style="font-family:Comic Sans MS; font-size:18px">private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
JSONObject object = (JSONObject) msg.obj;
try {
txt_weather_city.setText(object.getString("city"));
txt_weather_temp.setText(object.getString("temp2")+"/"+object.getString("temp1"));
txt_weather_detail.setText(object.getString("weather"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};</span>
當然還有一個問題就是城市名字我是寫死的,建議可以使用百度地圖的定位功能來獲取當前城市名稱,然後再使用!當然還會存在很多字符串的問題,比如深圳,深圳市等等,具體問題具體分析,按照需求處理就好了!
數據庫文件我放在了資源文件夾raw中了,通過讀取復制到當前程序的數據庫目錄下,這個工具方法挺好用的(之前一個同事的工具代碼),代碼如下:
[java]
<span style="font-family:Comic Sans MS; font-size:18px">/** 將資源文件中的數據庫文件復制到當前程序數據庫目錄下 */
public void copyDatabase() {
File file = new File(DB_PATH);
if (!file.isDirectory())
file.mkdir();
String dbfile = DB_PATH + "/" + DBNAME;//自己應用數據庫的名字
try {
if (new File(dbfile).length() == 0) {
FileOutputStream fos = new FileOutputStream(dbfile);
byte[] buffer = new byte[BUFFER_SIZE];
readDB(fos, buffer,<span style="color:#33ff33"> </span><span style="color:#3366ff">R.raw.citychina</span>);//數據庫文件的名稱
fos.close();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}</span>
[java]
<span style="font-family:Comic Sans MS; font-size:18px">private void readDB(FileOutputStream fos, byte[] buffer, int db_id)
throws IOException {
int count;
InputStream is;
is = this.context.getResources().openRawResource(db_id);
while ((count = is.read(buffer)) > 0) {
fos.write(buffer, 0, count);
}
is.close();
}</span>
至此使用中國天氣網,用城市名稱獲取天氣狀況的思路大致是這樣了,只是個人的拙見,本文同樣是留個備份案底,以便日後真正用起來不會抓狂!Demo和城市數據庫文件的下載地址如下,數據庫文件在demo的raw下面如果覺得有需要的話可以自行下載看看@_@