因为项目中需要用到天气预报功能,所以就自己研究了下,
欢迎转载请加地址http://blog.csdn.net/jing110fei/article/details/38515275
首先得找到一个能用的接口,网上出现频率最高的接口是
http://m.weather.com.cn/data/101070101.html 其中101070101就是城市对应的ID
但是完成后,发现此接口2014年3月4日以后就不再更新了
然后又开始寻找,最后还是中国天气网的另一个接口http://m.weather.com.cn/atad/101070101.html 这个是可以用的。
找到可以用的接口,基本就松口气了,接下来就是取数据的事了。
怎么取数据呢,我们一般是输入一个城市名字,期望得到它未来三天的天气状况,
看上面的接口就知道我们需要解决另一个问题,就是城市对应的ID,我也很抓狂,幸好在网上有前辈整理了基本全部的城市ID。。PS:不得不在这里给这位前辈点个赞!
如上图,将此文件放在了assets文件夹下,好了废话不说,贴出主要代码。
主文件的布局文件activity_weather_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/city_name" android:layout_width="0dp" android:layout_height="wrap_content" android:hint="请输入城市名字" android:layout_weight="1"/> <Button android:id="@+id/query_cityID" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="查询城市ID" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/city_id" android:layout_width="0dp" android:layout_height="wrap_content" android:background="@drawable/setbar_bg" android:hint="将在此处显示城市ID" android:textSize="18sp" android:layout_weight="1"/> <Button android:id="@+id/query_weather" android:layout_width="0dp" android:layout_height="wrap_content" android:text="查询天气" android:layout_weight="1" /> </LinearLayout> <ListView android:id="@+id/query_list" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
然后是listview的显示布局listview_form.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="horizontal" > <TextView android:id="@+id/name" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_marginLeft="20dp" /> <TextView android:id="@+id/message" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" /> </LinearLayout>
然后是主MainActivity的代码WeatherMainActivity.java
public class WeatherMainActivity extends Activity implements OnClickListener { //定义 输入城市名字控件 private EditText citynameText; //定义查询城市ID和查询天气的两个Button private Button query_city_id,query_weather; //定义显示城市ID的TextView private TextView cityIDView; //listview用于显示查询到的天气信息 private ListView listview; //listview需要的显示格式即是一个个的键值对,比如天气--------晴 private HashMap<String,String> message_map; //listview需要的天气显示格式 将上面的键值对全部存起来 private ArrayList<HashMap<String,String>> message_list; //用于线程间通讯 private Handler handler; //发送消息更新视图 private static final int VIEW_UPDATE=1; private SimpleAdapter SA; //查询天气线程 private Thread thread; //定义城市名字和ID String name=""; String id=""; //判断获取天气数据成功与否的标识 private int count=0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_weather_main); citynameText=(EditText)findViewById(R.id.city_name); cityIDView=(TextView)findViewById(R.id.city_id); //用来查找城市ID query_city_id=(Button)findViewById(R.id.query_cityID); query_city_id.setOnClickListener(this); //用来查询天气 query_weather=(Button)findViewById(R.id.query_weather); query_weather.setOnClickListener(this); message_list = new ArrayList<HashMap<String,String>>(); listview = (ListView)findViewById(R.id.query_list); SA = new SimpleAdapter(this, message_list, R.layout.listview_form, new String[]{"name","message"}, new int[]{R.id.name,R.id.message}); listview.setAdapter(SA); //定义handle对返回结果进行响应 handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case VIEW_UPDATE: //更新listView的数据 SA.notifyDataSetChanged(); break; case 3: Toast.makeText(WeatherMainActivity.this, "查询天气失败,可能是网络原因,请检查网络连接", Toast.LENGTH_SHORT).show(); break; default: break; } } }; } public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.query_cityID: name=citynameText.getText().toString(); id=findId(name); if(null==id||"".equals(id)){ Toast.makeText(WeatherMainActivity.this, "在集合中,没有找到对应城市id", 1).show(); }else{ cityIDView.setText(id); } break; case R.id.query_weather: if (null==id||"".equals(id)) { Toast.makeText(WeatherMainActivity.this, "请先查询城市ID", 1).show(); }else { queryWeather(); } break; default: break; } } private String findId(String cityname){ if(null==cityname||"".equals(cityname)) return null; try { InputStreamReader inputReader = new InputStreamReader(getResources().getAssets().open("citycode.txt") ); BufferedReader bufReader = new BufferedReader(inputReader); String line=""; String[] str = new String[2]; while((line = bufReader.readLine()) != null){ str = line.split("="); if(str.length==2&&null!=str[1]&&!"".equals(str[1])&&cityname.equals(str[1])){ //返回对应编号 return str[0]; } } } catch (Exception e) { e.printStackTrace(); return null; } return null; } // 向中国天气网查询数据 private void queryWeather(){ thread = new Thread(){ @Override public void run() { super.run(); //创建返回的天气信息对象,是一个对象数组,用来放3天的天气 WeatherForm[] WF = new WeatherForm[3]; //查询天气,返回3天的天气信息 WeatherQueryManage WQM = new WeatherQueryManageImpl(); WF = WQM.weatherquery(id); message_list.clear(); if(WF.length>=1){ message_map = new HashMap<String, String>(); message_map.put("name", WF[0].getName()+":"); message_map.put("message", WF[0].getDdate()+"-"+WF[0].getWeek()); message_list.add(message_map); for(int i=0;i<WF.length;i++){ message_map = new HashMap<String, String>(); if(i==0){ message_map.put("name", "--------"); message_map.put("message", "--------今天--------------"); message_list.add(message_map); } if(i==1){ message_map.put("name", "--------"); message_map.put("message", "--------明天--------------"); message_list.add(message_map); } if(i==2){ message_map.put("name", "--------"); message_map.put("message", "--------后天--------------"); message_list.add(message_map); } message_map = new HashMap<String, String>(); message_map.put("name", "温度:"); message_map.put("message",WF[i].getTemp()); message_list.add(message_map); message_map = new HashMap<String, String>(); message_map.put("name", "天气状况:"); message_map.put("message", WF[i].getWeather()); message_list.add(message_map); message_map = new HashMap<String, String>(); message_map.put("name", "风力:"); message_map.put("message", WF[i].getWind()); message_list.add(message_map); if(WF[i].getWind()==null||"".equals(WF[i].getWind())){ ++count; } } } if(count==3){ Message message = new Message(); message.what=count; handler.sendMessage(message); }else { Message message = new Message(); message.what=VIEW_UPDATE; handler.sendMessage(message); } } }; thread.start(); } }
接下来是查询到的数据定义为天气对象WeatherForm.java
public class WeatherForm { //城市名 private String name; //城市编号 private String id; //当前日期 private String ddate; //星期 private String week; //温度 private String temp; //天气描述 private String weather; //风力 private String wind; //风向 private String fx; public WeatherForm(){ } public WeatherForm(String name, String id, String ddate, String week, String temp, String weather, String wind, String fx) { super(); this.name = name; this.id = id; this.ddate = ddate; this.week = week; this.temp = temp; this.weather = weather; this.wind = wind; this.fx = fx; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getDdate() { return ddate; } public void setDdate(String ddate) { this.ddate = ddate; } public String getWeek() { return week; } public void setWeek(String week) { this.week = week; } public String getTemp() { return temp; } public void setTemp(String temp) { this.temp = temp; } public String getWeather() { return weather; } public void setWeather(String weather) { this.weather = weather; } public String getWind() { return wind; } public void setWind(String wind) { this.wind = wind; } public String getFx() { return fx; } public void setFx(String fx) { this.fx = fx; } @Override public String toString() { return "WeatherForm [name=" + name + ", id=" + id + ", ddate=" + ddate + ", week=" + week + ", temp=" + temp + ", weather=" + weather + ", wind=" + wind + ", fx=" + fx + "]"; } }
接下来是查询天气的接口的定义WeatherQueryManage.java
public interface WeatherQueryManage { //查询天气方法 // 参数 CityId 对应城市的id //返回值 暂时返回3天的天气数据 public WeatherForm[] weatherquery(String CityId); }
然后是对应接口的实现
public class WeatherQueryManageImpl implements WeatherQueryManage { public WeatherForm[] weatherquery(String CityId) { WeatherForm[] WF = new WeatherForm[3]; //http://m.weather.com.cn/data/101070101.html //String URL = "http://m.weather.com.cn/data/"+CityId+".html"; //http://m.weather.com.cn/atad/101070101.html String URL="http://m.weather.com.cn/atad/"+CityId+".html"; String Weather_Result=""; HttpGet httpRequest = new HttpGet(URL); // 获得HttpResponse对象 try { HttpClient httpClient = new DefaultHttpClient(); HttpResponse httpResponse = httpClient.execute(httpRequest); if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { // 取得返回的数据 Weather_Result = EntityUtils.toString(httpResponse.getEntity()); } } catch (Exception e) { WF[0] = new WeatherForm(); WF[1] = new WeatherForm(); WF[2] = new WeatherForm(); return WF; } //以下是对返回JSON数据的解析 if(null!=Weather_Result&&!"".equals(Weather_Result)){ try { JSONObject JO = new JSONObject(Weather_Result).getJSONObject("weatherinfo"); // for(int i=0;i<WF.length;i++){ WeatherForm weaf = new WeatherForm(); weaf.setName(JO.getString("city")); weaf.setDdate(JO.getString("date_y")); weaf.setWeek(JO.getString("week")); weaf.setTemp(JO.getString("temp"+(i+1))); weaf.setWind(JO.getString("wind"+(i+1))); weaf.setWeather(JO.getString("weather"+(i+1))); WF[i]=weaf; } } catch (JSONException e) { WF[0] = new WeatherForm(); WF[1] = new WeatherForm(); WF[2] = new WeatherForm(); return WF; } } return WF; } }
以上就是全部代码了。。。我这里运行正常,在接口的实现里,第一个注释掉的网址就是之前说的那个不更新的那个地址
对了,别忘了在AndroidManifest.xml中加上访问网络的权限。
<uses-permission android:name="android.permission.INTERNET"/>
OK,结束了,欢迎各位童鞋一起来讨论哈,有好的想法也希望能够告诉我。