[Android] AlertDialog获取网上天气并显示各城市天气
? ? 最近幫同學做android百度地圖,其中涉及到定位城市天氣功能.才知道自己技術非常的一般,還有很多東西需要學習,同時需要回歸到我研究生的方向——數據挖掘.同時又見識到了一位叫柳峰的大神,推薦大家去看看他的文章,好像他還是貴州的老鄉.博文地址:http://blog.csdn.net/lyq8479/
? ? 言歸正傳,我主要通過兩種方法實現:
? ? 1.第一種方法是通過調用中國天氣網信息實現的,它的思想是通過查詢靜態數據庫中個城市對應的WeatherCode,在通過訪問中國天氣網獲取JSON格式數據顯示,天氣對應的圖片也從網上獲取.
? ? 2.第二種方法是通過新浪天氣API接口實現的,它只需要輸入查詢的具體城市或縣城即可獲取JSON格式天氣,而且天氣對應圖片采用res中靜態的對應.
? ? 參考資料:
? ? 中國天氣網網上資料較多,主要參考郭神《Android第一行代碼》
? ? http://smart.weather.com.cn/wzfw/smart/weatherapi.shtml
? ??http://blog.csdn.net/eyu8874521/article/details/11574485
? ??http://blog.csdn.net/lzqwebsoft/article/details/7054045
? ? http://blog.csdn.net/pi9nc/article/details/9297085?
?
一. 中國天氣網獲取天氣信息介紹
? ? 中國天氣網提供了獲取天氣及各個城市的代號信息.通過下面兩種接口方法獲取北京天氣,而獲取詳細信息的接口可能已更改.
? ? 1.簡單信息?http://www.weather.com.cn/data/cityinfo/101010100.html
? ? 2.簡單信息?http://www.weather.com.cn/data/sk/101010100.html
{"weatherinfo":{"city":"北京","cityid":"101010100","temp":"1","WD":"東南風","WS":"2級","SD":"58%","WSE":"2","time":"18:15","isRadar":"1","Radar":"JC_RADAR_AZ9010_JB","njd":"暫無實況","qy":"1024"}}? ? 程序主要通過該URL獲取城市的天氣,其中101010100表示的就是北京的天氣代號,它是如何獲取的呢?同樣中國天氣網提供了網址獲取不同城市/縣城的天氣代號.
? ??http://www.weather.com.cn/data/list3/city.xml
? ? 服務器會返回省份名稱+省級代號(一級列表,包括省/直轄市/自治區).如下:
? ?在輸入省級代號獲取二級碼,如北京city01,貴州city26
? ??http://www.weather.com.cn/data/list3/city26.xml
? ? 此時你如果你對地理熟悉,你可以發現它們分別是每個省的地區,同樣道理可以獲取每個地區的縣份或區的編碼.如輸入city2605
? ??http://www.weather.com.cn/data/list3/city2605.xml
? ? 通過這種方法就可以把全國所有省、市、縣地區的天氣都實時獲取.如下是凱里市對應的天氣代號
? ??http://www.weather.com.cn/data/list3/city260501.xml
? ? 到了此處,想必你也知道如果獲取凱里市的天氣了吧.就是輸入網址
? ??http://www.weather.com.cn/data/cityinfo/101260501.html
? ? 其中天氣圖標可通過網站查看,而獲取具體圖標網址忘記記錄了.
? ??http://www.weather.com.cn/static/html/legend.shtml
二. 源碼顯示城市天氣
? ?這里就看著郭神的書實現吧,那個界面挺好看的.同時我自定義的AlertDialog對話框也挺好看的.? ? 1.布局文件 activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:background="#484E61" ><Buttonandroid:id="@+id/close_weather"android:layout_width="30dp"android:layout_height="30dp"android:layout_centerVertical="true"android:layout_marginLeft="10dp"android:background="@drawable/home" /><TextViewandroid:id="@+id/city_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:textColor="#fff"android:textSize="24sp" /><Buttonandroid:id="@+id/refresh_weather"android:layout_width="30dp"android:layout_height="30dp"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_marginRight="10dp"android:background="@drawable/refresh" /></RelativeLayout><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"android:background="#27A5F9" ><TextViewandroid:id="@+id/publish_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_marginRight="10dp"android:layout_marginTop="10dp"android:textColor="#FFF"android:textSize="18sp" /><LinearLayoutandroid:id="@+id/weather_info_layout"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:orientation="vertical" ><TextViewandroid:id="@+id/current_date"android:layout_width="wrap_content"android:layout_height="40dp"android:gravity="center"android:textColor="#FFF"android:textSize="18sp" /><TextViewandroid:id="@+id/weather_desp"android:layout_width="wrap_content"android:layout_height="60dp"android:layout_gravity="center_horizontal"android:gravity="center"android:textColor="#FFF"android:textSize="40sp" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="60dp"android:layout_gravity="center_horizontal"android:orientation="horizontal" ><TextViewandroid:id="@+id/temp1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:textColor="#FFF"android:textSize="40sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_marginLeft="10dp"android:layout_marginRight="10dp"android:text="~"android:textColor="#FFF"android:textSize="40sp" /><TextViewandroid:id="@+id/temp2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:textColor="#FFF"android:textSize="40sp" /></LinearLayout></LinearLayout></RelativeLayout></LinearLayout> ? ?2.在res/drawable-hdpi文件夾中添加兩張按鈕圖片home.png和refresh.png
? ?3.MainActivity.java
? public class MainActivity extends Activity implements OnClickListener {//自定義變量private TextView cityNameText; //用于顯示城市名private TextView publishText; //用于顯示發布時間private TextView weatherDespText; //用于顯示天氣描述信息private TextView temp1Text; //用于顯示最低氣溫private TextView temp2Text; //用于顯示最高氣溫private TextView currentDateText; //用于顯示當前日期private Button closeWeather; //退出程序private Button refreshWeather; //更新天氣按鈕private String weatherCode; //天氣代碼private String weatherJson; //獲取JSON格式@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);//獲取對象cityNameText = (TextView) findViewById(R.id.city_name);publishText = (TextView) findViewById(R.id.publish_text);weatherDespText = (TextView) findViewById(R.id.weather_desp);temp1Text = (TextView) findViewById(R.id.temp1);temp2Text = (TextView) findViewById(R.id.temp2);currentDateText = (TextView) findViewById(R.id.current_date);closeWeather = (Button) findViewById(R.id.close_weather);refreshWeather = (Button) findViewById(R.id.refresh_weather);//主活動 implements OnClickListenercloseWeather.setOnClickListener(this);refreshWeather.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.close_weather:finish();break;case R.id.refresh_weather:DialogChooseCity();break;default:break;}}/*** 自定義對話框 獲取城市* 中國天氣網 * http://www.weather.com.cn/data/cityinfo/101010100.html*/private void DialogChooseCity() {//創建對話框AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);builder.setTitle("請選擇一個城市");builder.setIcon(android.R.drawable.ic_dialog_info);//指定下拉列表的顯示數據final String[] cities = {"北京", "上海", "天津", "廣州", "貴陽", "臺北", "香港"};final String[] codes = {"101010100", "101020100", "101030100","101280101","101260101", "101340101", "101320101"};builder.setItems(cities, new DialogInterface.OnClickListener(){@Overridepublic void onClick(DialogInterface dialog, int which){weatherCode = codes[which];//執行線程訪問http//否則 NetworkOnMainThreadExceptionnew Thread(new Runnable() {@Overridepublic void run() {//訪問中國天氣網String weatherUrl = "http://www.weather.com.cn/data/cityinfo/"+ weatherCode + ".html";weatherJson = queryStringForGet(weatherUrl);//JSON格式解析try {JSONObject jsonObject = new JSONObject(weatherJson);JSONObject weatherObject = jsonObject.getJSONObject("weatherinfo");Message message = new Message();message.obj = weatherObject;handler.sendMessage(message);} catch (JSONException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}).start();}});builder.show();}/*** 解析Json格式數據并顯示*/@SuppressLint("HandlerLeak")Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubsuper.handleMessage(msg);JSONObject object = (JSONObject) msg.obj;try {cityNameText.setText(object.getString("city"));temp1Text.setText(object.getString("temp1"));temp2Text.setText(object.getString("temp2"));weatherDespText.setText(object.getString("weather"));publishText.setText("今天"+object.getString("ptime")+"發布");//獲取當前日期SimpleDateFormat sdf = new SimpleDateFormat("yyyy年M月d日", Locale.CHINA);currentDateText.setText(sdf.format(new Date()));} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}};/*** 網絡查詢*/private String queryStringForGet(String url) {HttpGet request = new HttpGet(url);String result = null;try {HttpResponse response = new DefaultHttpClient().execute(request);if (response.getStatusLine().getStatusCode() == 200) {result = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);return result;}} catch (ClientProtocolException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return result;}} ? ? 4.最后在AndroidManifest.xml中聲明網絡權限 <!-- 申請權限 --> <uses-permission android:name="android.permission.INTERNET" />
? ?5.運行效果如下圖所示
? ?????
? ?6.需要注意幾點
? ? (1)在訪問http或獲取上傳網絡數據時,你可能會遇到錯誤導致程序崩潰,即錯誤NetworkOnMainThreadException.你需要自定義線程實現,通過:
? ? (3)如果可能通過自定義DBHelper(繼承自SQLiteOpenHelper)和DBManager獲取靜態數據庫中數據,查看對應城市或縣份的天氣代碼.但是重新移植數據庫總是報錯"no such table:city_table".但是明明存在,可能是數據庫路徑"/data/data/包名/databases/mydata.db"定義或引用錯誤,仍未解決.
? ? 通過SQLiteSpy軟件打開db文件,很明顯存在city_table表和數據.如下圖所示: ? ? ?(4)學會自定義AlertDialog并調用它,同時獲取網絡圖片那個URL當時查看到沒記錄,可惜了.
? ? PS:最后推薦看看郭神《Android第一行代碼》第十四章關于天氣的講解,但基本原理和方法該文章我都已經講述了.
?
三. 新浪天氣API實現
? ? 新浪天氣API方法同上,但唯一不同點是輸入城市名稱.這樣就不需要再次獲取WeatherCode,訪問網址如下:
? ??http://php.weather.sina.com.cn/iframe/index/w_cl.php?code=js&day=2&city=北京&dfc=3
? ? 如獲取北京的新浪天氣,返回的JSON格式如下:
? ? 程序中顯示效果如下圖所示,顯示的時候是參考了huanghsh的模板,但是不知道它源地址.所以見諒!否則推薦大家去下載看看~
? ?? ? ?其中原理與上面相同,通過調用HttpService.getWeather(cityName)函數獲取天氣.其中自定義類HttpService代碼中getWeather如下,而DefaultHttpClient是自定義設置代理. public static String getWeather(String city){ String result=null;String url="http://php.weather.sina.com.cn/iframe/index/w_cl.php?code=js&day=2&city="+city+"&dfc=3";try{ DefaultHttpClient client = getDefaultHttpClient2(); HttpGet mothod = new HttpGet(url); HttpResponse httpResponse = client.execute(mothod);if (httpResponse.getStatusLine().getStatusCode() == 200) { result = EntityUtils.toString(httpResponse.getEntity(),"gb2312"); } }catch(Exception ex){ ex.printStackTrace(); } return result; } ? ?而天氣圖片是通過res/drawable文件夾下靜態圖片顯示,該方法也介紹下! private int imageResoId(String weather){int resoid=R.drawable.s_2;if(weather.indexOf("多云")!=-1||weather.indexOf("晴")!=-1){//多云轉晴,以下類同 indexOf:包含字串resoid=R.drawable.s_1;}else if(weather.indexOf("多云")!=-1&&weather.indexOf("陰")!=-1){resoid=R.drawable.s_2;}else if(weather.indexOf("陰")!=-1&&weather.indexOf("雨")!=-1){resoid=R.drawable.s_3;}else if(weather.indexOf("晴")!=-1&&weather.indexOf("雨")!=-1){resoid=R.drawable.s_12;}else if(weather.indexOf("晴")!=-1&&weather.indexOf("霧")!=-1){resoid=R.drawable.s_12;}else if(weather.indexOf("晴")!=-1){resoid=R.drawable.s_13;}else if(weather.indexOf("多云")!=-1){resoid=R.drawable.s_2;}else if(weather.indexOf("陣雨")!=-1){resoid=R.drawable.s_3;}else if(weather.indexOf("小雨")!=-1){resoid=R.drawable.s_3;}else if(weather.indexOf("中雨")!=-1){resoid=R.drawable.s_4;}else if(weather.indexOf("大雨")!=-1){resoid=R.drawable.s_5;}else if(weather.indexOf("暴雨")!=-1){resoid=R.drawable.s_5;}else if(weather.indexOf("冰雹")!=-1){resoid=R.drawable.s_6;}else if(weather.indexOf("雷陣雨")!=-1){resoid=R.drawable.s_7;}else if(weather.indexOf("小雪")!=-1){resoid=R.drawable.s_8;}else if(weather.indexOf("中雪")!=-1){resoid=R.drawable.s_9;}else if(weather.indexOf("大雪")!=-1){resoid=R.drawable.s_10;}else if(weather.indexOf("暴雪")!=-1){resoid=R.drawable.s_10;}else if(weather.indexOf("揚沙")!=-1){resoid=R.drawable.s_11;}else if(weather.indexOf("沙塵")!=-1){resoid=R.drawable.s_11;}else if(weather.indexOf("霧")!=-1){resoid=R.drawable.s_12;}return resoid; } ? ?其中自定義對話框輸入AlertDialog,載入weather_other_city.xml布局僅有一個輸入框ExitText控件.通過Intent傳參至顯示天氣的界面.具體代碼如下.? //輸入城市名 private void showOtherCity() {LayoutInflater inflater = getLayoutInflater();View layout = inflater.inflate(R.layout.weather_other_city,(ViewGroup) findViewById(R.id.ws_dialog));dialogCity = (EditText)layout.findViewById(R.id.ws_city_name);//創建對話框new AlertDialog.Builder(this).setTitle("請輸入城市名稱").setView(layout).setPositiveButton("確定",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int id) {cityName = dialogCity.getText().toString();Intent intent = new Intent(MainActivity.this, WeatherScreen.class);intent.putExtra("extra_data", cityName);startActivity(intent);}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int id) {dialog.cancel();}}).show(); } ? ?由于新浪方法類似,所以就簡述了些其他如顯示靜態圖片和AlertDialog的知識.
? ?最后簡單總結下吧!第一種方法主要通過中國天氣網顯示信息,其核心是獲取天氣代碼WeatherCode,然后訪問URL獲取JSON格式數據并顯示.第二種方法僅僅是傳入城市名稱(不要傳錯),然后獲取JSON數據顯示天氣即可.最后希望文章對大家有所幫助,如果有錯誤或不足之處,還請海涵~
? ?(By:Eastmount 2014-12-18 晚9點?http://blog.csdn.net/eastmount/)
?
總結
以上是生活随笔為你收集整理的[Android] AlertDialog获取网上天气并显示各城市天气的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [android] No resourc
- 下一篇: [android] 百度地图开发 (一)