龔世文+朱忠敏
摘要:Android體系結(jié)構(gòu)采用軟件堆層(Software Stack)的架構(gòu),提供一系列的核心應(yīng)用程序包括瀏覽器、電子郵件客戶端、通訊錄和日歷等,其市場(chǎng)份額長(zhǎng)年保持在50%以上,無(wú)論從技術(shù)層面還是受眾范圍來(lái)看都是非常合適的應(yīng)用開(kāi)發(fā)平臺(tái)。
關(guān)鍵詞:Android平臺(tái);系統(tǒng)設(shè)計(jì);大氣環(huán)境
中圖分類號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2016)10-0073-04
1 概述
中國(guó)經(jīng)濟(jì)在過(guò)去40年快速的發(fā)展極大地提高了人民生活水平,同時(shí)也引起了嚴(yán)重的環(huán)境問(wèn)題。早在2007年Cyranoski便在《自然》雜志撰文指出大氣污染已經(jīng)成為困擾大多數(shù)中國(guó)城市的嚴(yán)重問(wèn)題。2009年以來(lái),在國(guó)內(nèi)外輿論的引導(dǎo)下大氣污染問(wèn)題逐步從一個(gè)學(xué)術(shù)性議題演變?yōu)檎涡缘拇蟊娮h題。2014年起,環(huán)境保護(hù)部開(kāi)始通過(guò)其官方網(wǎng)站正式對(duì)公眾發(fā)布實(shí)時(shí)PM2.5數(shù)據(jù)。數(shù)據(jù)的公開(kāi)發(fā)布有助消除公眾的疑慮,同時(shí)對(duì)公共健康起到了指導(dǎo)作用。隨著“互聯(lián)網(wǎng)+”時(shí)代的到來(lái),大眾獲取信息的主要手段已經(jīng)從電視廣播報(bào)紙轉(zhuǎn)變?yōu)榫W(wǎng)絡(luò),而智能手機(jī)的普及化進(jìn)一步提升了大眾獲取信息的能力。相比于網(wǎng)頁(yè)模式,手機(jī)端應(yīng)用的最大優(yōu)勢(shì)在于可以智能定位,隨時(shí)隨地獲取最新數(shù)據(jù)。Android體系結(jié)構(gòu)采用軟件堆層(Software Stack)的架構(gòu),提供一系列的核心應(yīng)用程序包括瀏覽器、電子郵件客戶端、通訊錄和日歷等,其市場(chǎng)份額長(zhǎng)年保持在50%以上,無(wú)論從技術(shù)層面還是受眾范圍來(lái)看都是非常合適的應(yīng)用開(kāi)發(fā)平臺(tái)。因此,在Android系統(tǒng)下,開(kāi)發(fā)一款能夠?qū)崟r(shí)查詢所處位置空氣質(zhì)量和天氣情況的手機(jī)應(yīng)用是一個(gè)具有明顯用戶需求的任務(wù)。
2 系統(tǒng)設(shè)計(jì)
一般的空氣質(zhì)量查詢應(yīng)用只能對(duì)大氣顆粒物(PM2.5和PM10)和大氣污染物(SO2、CO、NOX和O3)進(jìn)行查詢。考慮到氣象因素與大氣污染存在一定關(guān)聯(lián),而且這兩個(gè)因素共同決定了用戶進(jìn)行室外運(yùn)動(dòng)的意愿。因此,本文所提應(yīng)用程序劃分為空氣質(zhì)量查詢和天氣查詢兩大功能??諝赓|(zhì)量查詢功能部分劃分為用戶界面、網(wǎng)上數(shù)據(jù)獲取與解析、數(shù)據(jù)適配器和相關(guān)知識(shí)查詢四個(gè)模塊;天氣查詢功能部分用戶界面、數(shù)據(jù)獲取與解析、數(shù)據(jù)庫(kù)適配器三個(gè)模塊。各個(gè)模塊之間的關(guān)系如下圖1所示。
圖 1 應(yīng)用總體設(shè)計(jì)思想
在空氣質(zhì)量查詢功能模塊中,當(dāng)用戶通過(guò)界面發(fā)送請(qǐng)求時(shí),空氣質(zhì)量數(shù)據(jù)獲取子模塊負(fù)責(zé)從中國(guó)環(huán)境監(jiān)測(cè)總站城市空氣質(zhì)量實(shí)時(shí)發(fā)布平臺(tái)加載數(shù)據(jù)信息,然后進(jìn)行數(shù)據(jù)解析顯示在用戶界面上。氣象數(shù)據(jù)查詢模塊的流程與前者相似,唯一不同在于使用了不同的解析技術(shù)。JSON相對(duì)于XML,速率快,數(shù)據(jù)的體積小,JSON與JavaScript的交互更加方便,但JSON對(duì)數(shù)據(jù)的描述性比XML較差。因而結(jié)合兩者解析的優(yōu)缺點(diǎn)以及服務(wù)端返回?cái)?shù)據(jù)格式,在解析空氣質(zhì)量數(shù)據(jù)時(shí)使用JSON解析,在解析天氣數(shù)據(jù)時(shí)使用XML的Pull解析。
3功能實(shí)現(xiàn)
3.1程序設(shè)計(jì)
通過(guò)JSON方式實(shí)現(xiàn)PM2.5數(shù)據(jù)解析,通過(guò)定義JSONArray和JSONObject獲取大氣環(huán)境的相關(guān)數(shù)據(jù),包括AQI、城市名、PM2.5、PM10、首要污染物、污染級(jí)別等,主要代碼如下所示:
protected void onPostExecute(String result) {
ArrayList
if (result != null && !result.contains("error")) {
Log.d(PM25Provider.LogTag, result);
try { JSONArray localJSONArray = new JSONArray(result);
pm25List = new ArrayList
for (int i = 0; i < localJSONArray.length(); i++) {
JSONObject localJSONObject = localJSONArray.getJSONObject(i);
PM25Provider.PM25 pm25 = new PM25Provider.PM25();
pm25.aqi = localJSONObject.optString("aqi");
pm25.area = localJSONObject.optString("area");
pm25.pm2_5 = localJSONObject.optString("pm2_5");
pm25.pm10 = localJSONObject.optString("pm10");
pm25.position_name = localJSONObject.optString("position_name");
pm25.primary_pollutant = localJSONObject.optString("primary_pollutant");
pm25.quality = localJSONObject.optString("quality");
pm25.time_point = localJSONObject.optString("time_point");
pm25List.add(pm25); }
} catch (JSONException e) { e.printStackTrace();
} pm25Listener.onInfo(pm25List); } }
在此基礎(chǔ)上,利用API.java訪問(wèn)網(wǎng)絡(luò)接口并設(shè)置城市名字符串;利用PM25Adapter.java將數(shù)據(jù)加載于界面布局;PM25Citysetting.java實(shí)現(xiàn)城市選擇功能;PM25Activity.java完成主界面顯示響應(yīng)功能,首先設(shè)置分享部分響應(yīng),其次設(shè)置初次顯示界面數(shù)據(jù),之后設(shè)置動(dòng)態(tài)打印報(bào)告數(shù)據(jù)加載顯示以及用戶反饋動(dòng)態(tài)效果響應(yīng)問(wèn)題,最后通過(guò)調(diào)用其他Activity完成數(shù)據(jù)成功顯示??諝赓|(zhì)量報(bào)告顯示主要代碼如下所示:
new PM25Provider().request(new PM25Provider.PM25Info() {
public void onInfo(List
if (pm25List == null) {
Toast.makeText(PM25Activity.this, R.string.get_pm25_fail,
Toast.LENGTH_SHORT).show();
return; }
PM25Provider.PM25 pm25 = (PM25Provider.PM25) pm25List.get(-1
+ pm25List.size());
vAQI = wrapFont(pm25.aqi);
vPM25 = wrapFont(pm25.pm2_5);
mPaperAQI.setText(vAQI);
try {
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
.parse(pm25.time_point);
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy年MM月dd日 HH:mm");
vTime = sdf.format(date);
mPaperTime.setText("發(fā)布時(shí)間:" + vTime);
vCity = pm25.area;
mPaperArea.setText(vCity);
vQuality = pm25.quality;
mPaperQuality.setText("等級(jí):" + vQuality);
mPaperProposal.setText("建議:" + (String) maps.get(vQuality));
mValue.setText("88888 ");
mListView.setAdapter(new PM25Adapter(PM25Activity.this,
pm25List));
startInfoShow();
} catch (ParseException e) {
e.printStackTrace();
}
}
}, city);
}
氣象功能實(shí)現(xiàn)代碼包:com.weaher,其中Config.java配置信息類;DBAdapter.java實(shí)現(xiàn)數(shù)據(jù)庫(kù)配置;Forecast.java未來(lái)天氣類;Weather.java當(dāng)前天氣類;WeatherAdapter.java數(shù)據(jù)獲取模塊,使用XML Pull解析數(shù)據(jù);WeatherDemo.java該功能的程序啟動(dòng)默認(rèn)界面響應(yīng)。
在WeatherAdapter.java數(shù)據(jù)獲取模塊中首先設(shè)置靜態(tài)變量getWeather,通過(guò)HttpClient的get或post方式請(qǐng)求服務(wù)器,然后建立XmlPullParser解析器解析服務(wù)器返回的數(shù)據(jù),使用while if語(yǔ)句獲取四天內(nèi)weather的時(shí)間、地點(diǎn)、溫度、氣候、風(fēng)力,其在Forecast.java和Weather.java中定義好需要獲取的變量數(shù)據(jù)名。
Pull解析代碼如下面所示:
private static void getWeatherData(String city) throws IOException,Throwable{
String requestUrl = "http://api.map.baidu.com/telematics/v3/weather?location="
+city +"&output=xml&ak=A72e372de05e63c8740b2622d0ed8ab1";
String result = request("POST",requestUrl);
InputStream streamTemp = new ByteArrayInputStream(result.getBytes());
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser();
parser.setInput(streamTemp,"UTF-8");
while(parser.next()!=XmlPullParser.END_DOCUMENT){
String element = parser.getName();
if(element != null && element.equals("weather_data")){
for(int dayCount = 0;dayCount<4;++dayCount){
if(dayCount == 0){
Weather.city = city;
System.out.println(city); }
while(parser.next()!=XmlPullParser.END_DOCUMENT){
element = parser.getName();
if((element != null)){
if (element.equals("date")) {
if(dayCount == 0)
Weather.current_date_time = parser.nextText();
else
Weather.day[dayCount-1].day_of_week = parser.nextText(); }
else if (element.equals("dayPictureUrl")) {
if(dayCount == 0)
Weather.current_dayPictureUrl = parser.nextText();
else
Weather.day[dayCount-1].dayPictureUrl = parser.nextText(); }
else if (element.equals("nightPictureUrl")) {
if(dayCount == 0)
Weather.current_nightPictureUrl = parser.nextText();
else
Weather.day[dayCount-1].nightPictureUrl = parser.nextText(); }
else if (element.equals("weather")) {
if(dayCount == 0)
Weather.current_weather = parser.nextText(); else
Weather.day[dayCount-1].weather = parser.nextText(); }
else if (element.equals("wind")) {
if(dayCount == 0)
Weather.current_wind = parser.nextText(); else
Weather.day[dayCount-1].wind = parser.nextText(); }
else if (element.equals("temperature")) {
if(dayCount == 0)
Weather.current_temp = parser.nextText(); else
Weather.day[dayCount-1].temperature = parser.nextText(); break;
}
服務(wù)器請(qǐng)求代碼如下所示:
private static String request(String method, String url) {
HttpResponse httpResponse = null;
StringBuffer result = new StringBuffer();
try {
if (method.equals("GET")) {
HttpGet httpGet = new HttpGet(url);
HttpClient httpClient = new DefaultHttpClient();
httpResponse = httpClient.execute(httpGet);
HttpEntity httpEntity = httpResponse.getEntity();
result.append(EntityUtils.toString(httpEntity, "utf-8"));
StatusLine statusLine = httpResponse.getStatusLine();
result.append(":" + statusLine.getProtocolVersion() + "\r\n");
int statusCode = statusLine.getStatusCode();
result.append(":" + statusCode + "\r\n");
} else if (method.equals("POST")) {
HttpPost httpPost = new HttpPost(url);
HttpClient httpClient = new DefaultHttpClient();
httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
result.append(EntityUtils.toString(httpEntity, "utf-8"));
}
} catch (Exception e)
3.2 UI展示
空氣質(zhì)量查詢界面設(shè)有城市選擇和查詢兩個(gè)按鈕,選擇按鈕可以選擇城市、實(shí)現(xiàn)PM2.5與AQI切換,查詢按鈕可以實(shí)現(xiàn)動(dòng)態(tài)效果。在連網(wǎng)的狀態(tài)下,可以自動(dòng)定位到當(dāng)前城市,顯示其AQI值,通過(guò)選擇按鍵可以切換PM2.5和AQI值,如圖2左1所示即為切換到PM2.5的狀態(tài)。當(dāng)點(diǎn)擊查詢會(huì)打印一份空氣質(zhì)量檢測(cè)報(bào)告,報(bào)告上顯示有標(biāo)題、發(fā)布時(shí)間、當(dāng)前城市名、AQI值、等級(jí)、建議措施、各監(jiān)測(cè)點(diǎn)PM2.5、PM10的值以及分享標(biāo)志,用戶可以分享到QQ、微信、微博等等一系列軟件中,效果如圖2左2至右1所示。
在天氣查詢界面中,主要顯示天氣實(shí)時(shí)數(shù)據(jù)(包括地區(qū)、時(shí)間、溫度、氣候、風(fēng)力)、未來(lái)三天天氣數(shù)據(jù)(包括溫度、氣候)、城市選擇和城市保存設(shè)置。其整體布局是LinearLayout線性布局,局部運(yùn)用表格布局TableLayout和TableRow、TextView顯示未來(lái)三天數(shù)據(jù)信息,使用RelativeLayout布局和Button、EditText、TextView控件顯示城市設(shè)置信息。當(dāng)用戶選擇城市后,點(diǎn)擊保存設(shè)置按鈕,界面會(huì)顯示“城市設(shè)置成功”字樣,在網(wǎng)絡(luò)通暢的情況下,即可顯示城市天氣相關(guān)信息。而當(dāng)無(wú)網(wǎng)狀態(tài)下,全部顯示為null。如圖3所示。
4 結(jié)束語(yǔ)
通過(guò)虛擬機(jī)和移動(dòng)終端的測(cè)試表明,此應(yīng)用可以正常運(yùn)行。整體界面以藍(lán)色系為主,設(shè)計(jì)美觀,給人一種清新舒暢的視覺(jué)享受,操作簡(jiǎn)單,易于掌握。需要指出的是該應(yīng)用的空氣質(zhì)量數(shù)據(jù)和天氣數(shù)據(jù)全部來(lái)源于網(wǎng)絡(luò),因此在運(yùn)行時(shí)需確保系統(tǒng)環(huán)境的網(wǎng)絡(luò)流暢性。
參考文獻(xiàn):
[1] Cyranoski D. Satellite view alerts china to soaring pollution[J]. Nature 2005, 437: 12.
[2] Cyranoski D. Monitoring air pollution[J]. Nature 2007, 448: 518.
[3] 董冠洋. 2014年中國(guó)190個(gè)城市將實(shí)時(shí)發(fā)布PM2.5數(shù)據(jù)[N]. 中國(guó)新聞社,2013-12-31
[4] 關(guān)立勛.Android 應(yīng)用開(kāi)發(fā)深入學(xué)習(xí)實(shí)錄[M].北京:電子工業(yè)出版社,2013.
[5] 李斌.空氣質(zhì)量實(shí)時(shí)發(fā)布系統(tǒng)數(shù)據(jù)上傳問(wèn)題的探討[J].環(huán)境科學(xué)與技術(shù),2011,34(12H):242- 244.
[6] 趙啟明.Android典型技術(shù)模塊開(kāi)發(fā)詳解[M].北京:中國(guó)鐵道出版社,2012.
[7] 隆益民.Android應(yīng)用開(kāi)發(fā)[M].廣州:中山大學(xué)出版社,2010.
[8] 王灝,馬軍.Java完全自學(xué)手冊(cè)[M].北京:機(jī)械工業(yè)出版社,2006:20-55.
[9] 王國(guó)輝,李偉.Android開(kāi)發(fā)寶典[M].北京:機(jī)械工業(yè)出版社,2008.