现在的位置: 首页 > 综合 > 正文

Android 根据城市获取天气(天气预报)

2018年05月06日 ⁄ 综合 ⁄ 共 9515字 ⁄ 字号 评论关闭

因为项目中需要用到天气预报功能,所以就自己研究了下,

尴尬欢迎转载请加地址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,结束了,欢迎各位童鞋一起来讨论哈,有好的想法也希望能够告诉我。可怜

 

 

抱歉!评论已关闭.