首先是软件的主界面
接下来是APP的主要代码:
(1)MainActivity
package com.example.weather;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Connection;
import java.util.ArrayList;
import org.json.JSONObject;
import org.w3c.dom.Text;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.drawable.AnimationDrawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends Activity {
private ImageView refreshImageView;
private ImageView searchImageView;
private TextView cityTextView;
private TextView pmTextView;
private TextView tempertureTextView;
private TextView weatherTextView;
private TextView dateTextView;
private TextView netWorkErrorTextView;
private View pmStateColorView;
private LinearLayout futureDayWeatherListLayout;
private AnimationDrawable refreshAnimation;
private int cityCode;
private SharedPreferences sharePrefrences;
private Handler netWorkFinishHandler = new Handler() {
public void handleMessage(Message msg) {
//网络请求结束所以停掉动画
refreshAnimationStop();
// handleMessage 先区分不同的消息
if (msg.what == 404) {
netWorkErrorTextView.setText((String)msg.obj);
return;
}
if (msg.what == 100) {
// 网络请成功,数据解析完成
WeatherBean weatherBean = (WeatherBean) msg.obj;
cityTextView.setText(weatherBean.getCityName());
pmTextView.setText("PM:" + weatherBean.getPm() + "\r\r"
+ weatherBean.getPmLevel());
netWorkErrorTextView.setText("");
tempertureTextView.setText(weatherBean.getTemperture() + "℃");
weatherTextView.setText(weatherBean.getWeather() + "\r\r"
+ weatherBean.getWind() + "\r\r"
+ weatherBean.getWindLevel());
dateTextView.setText(weatherBean.getDateY()
+ weatherBean.getWeek());
setPmColor(weatherBean.getPmLevel());
setFutureDayWeather(weatherBean.getFutureWeatherList());
//获取sharePrefrences文件的编辑
Editor editor = sharePrefrences.edit();
//向编辑中添加一个键为cityCode的键值对并调用commit()方法写入到文件中
editor.putInt("cityCode", cityCode).commit();
}
}
private void setFutureDayWeather(
ArrayList<FutureWeatherBean> futureWeatherList) {
// 在向容器型控件添加布局时要先清空容器型控件
futureDayWeatherListLayout.removeAllViews();
for (int i = 0; i < futureWeatherList.size(); i++) {
FutureWeatherBean futureWeatherBean = futureWeatherList.get(i);
// 创建一个显示未来某天的布局
/*
* 把一个布局代码转化为View控件
* 通过布局转换器LayoutInflater对象的inflate(R.layout.futureday_layout,
* null)方法 获取LayoutInflater的对象用LayoutInflater的from(
* getApplicationContext() )静态方法来获取
*/
View futureDayLayout = LayoutInflater.from(
getApplicationContext()).inflate(
R.layout.futureday_layout, null);
// 从futureDayLayout中找到相关控件
TextView futureWeekTextView = (TextView) futureDayLayout
.findViewById(R.id.future_week_tv);
TextView futureWeatherTextView = (TextView) futureDayLayout
.findViewById(R.id.future_weather_tv);
TextView futureTempertureTextView = (TextView) futureDayLayout
.findViewById(R.id.future_temperture_tv);
// 给相关控件赋值
futureTempertureTextView.setText(futureWeatherBean
.getTemperture());
futureWeatherTextView.setText(futureWeatherBean.getWeather()
+ futureWeatherBean.getWind());
futureWeekTextView.setText(futureWeatherBean.getWeek());
// 把赋值完成的布局加载到横向ScrollView的布局中去
futureDayWeatherListLayout.addView(futureDayLayout);
}
}
private void setPmColor(String pmLevel) {
if (pmLevel.contains(getResources().getString(R.string.best))) {
pmStateColorView.setBackgroundColor(getResources().getColor(
R.color.green));
} else if (pmLevel.contains(getResources().getString(
R.string.better))) {
pmStateColorView.setBackgroundColor(getResources().getColor(
R.color.yellow));
} else if (pmLevel.contains(getResources().getString(
R.string.pollution))) {
pmStateColorView.setBackgroundColor(getResources().getColor(
R.color.orange));
} else if (pmLevel.contains(getResources().getString(
R.string.mpollution))) {
pmStateColorView.setBackgroundColor(getResources().getColor(
R.color.red));
} else if (pmLevel.contains(getResources().getString(
R.string.spollution))) {
pmStateColorView.setBackgroundColor(getResources().getColor(
R.color.violet));
} else {
pmStateColorView.setBackgroundColor(getResources().getColor(
R.color.brown));
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取sharePrefrences文件
sharePrefrences = getSharedPreferences("weather", Context.MODE_PRIVATE);
//从sharePrefrences文件中取出键为cityCode的值,如果sharePrefrences文件中没有键为cityCode的值,参数二为默认值
cityCode = sharePrefrences.getInt("cityCode", 101010100);
findViews();
setLisenter();
getWeatherDataFromNetWork();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//区分那个页面的返回值
if (requestCode == 300) {
//保存resultCode的值,resultCode就是搜索到的城市的Id
cityCode = resultCode;
getWeatherDataFromNetWork();
}
}
private void setLisenter() {
refreshImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
getWeatherDataFromNetWork();
}
});
searchImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, SearchCityCodeActivity.class);
//startActivityForResult(intent, 300);反向传值调用的启动Activity的方式
//参数二用于区分不同Activity的返回结果
startActivityForResult(intent, 300);
}
});
}
private void findViews() {
refreshImageView = (ImageView) findViewById(R.id.refresh_img);
searchImageView = (ImageView) findViewById(R.id.search_img);
cityTextView = (TextView) findViewById(R.id.city_tv);
pmTextView = (TextView) findViewById(R.id.pm_tv);
pmStateColorView = findViewById(R.id.pm_color_v);
tempertureTextView = (TextView) findViewById(R.id.temperture_tv);
weatherTextView = (TextView) findViewById(R.id.weather_tv);
dateTextView = (TextView) findViewById(R.id.date_tv);
netWorkErrorTextView = (TextView) findViewById(R.id.network_error_tv);
futureDayWeatherListLayout = (LinearLayout) findViewById(R.id.futureday_weather_layout);
}
private void getWeatherDataFromNetWork() {
ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netWorkInfo = manager.getActiveNetworkInfo();
if (netWorkInfo == null) {
netWorkErrorTextView.setText("网络异常,请检查网络");
return;
}
refreshAnimationStart();
new Thread(new Runnable() {
@Override
public void run() {
// 网络请求要先给出网址
String urlString = "http://weather.123.duba.net/static/weather_info/"+cityCode+".html";
// StringBuffer可变字符串 用于保存网络请求的结果
StringBuffer stringBuffer = new StringBuffer();
// 异常捕获建议把catch中的异常放大到所有的异常
try {
String resultString = NetWorkUtils.doGet(urlString);
// 异常处理resultString为空的情况
if (TextUtils.isEmpty(resultString)) {
// netWorkErrorTextView.setText("未请求到数据,请刷新");
netWorkRequestError("网络加载异常,请重新加载");
return;
}
// 确定请求到的数据包含天气信息
if (!resultString.contains("weather_callback")) {
netWorkRequestError("网络加载异常,请重新加载");
return;
}
WeatherBean weatherBean = new WeatherBean(resultString);
System.out.println(weatherBean.toString());
getWeatherDataSuccess(weatherBean);
} catch (Exception e) {
e.printStackTrace();
netWorkRequestError("网络加载异常,请重新加载");
}
}
private void getWeatherDataSuccess(WeatherBean weatherBean) {
Message message = new Message();
// message.what 是给这个消息设置一个唯一标识,handleMessage()中区分不同的消息
message.what = 100;
// message.obj 是保存要展示的数据对象,用于主线程刷新UI
message.obj = weatherBean;
// 通过handler对象的sendMessage()发送通知给主线程
netWorkFinishHandler.sendMessage(message);
}
}).start();
}
private void netWorkRequestError(String errorString){
Message message = new Message();
message.what = 404;
message.obj = errorString;
netWorkFinishHandler.sendMessage(message);
}
// 开启动画的方法
private void refreshAnimationStart() {
// 把动画资源设为refreshImage的背景
refreshImageView.setBackgroundResource(R.drawable.pb_bg);
// 从refreshImage上把动画资源取到
refreshAnimation = (AnimationDrawable) refreshImageView.getBackground();
// 启动动画资源
refreshAnimation.start();
// 当动画开启式,refreshImageView设为不可点击状态
refreshImageView.setEnabled(false);
}
//动画停止的方法
private void refreshAnimationStop(){
//停止动画
refreshAnimation.stop();
//把刷新按钮的图片放到refreshImageView上
refreshImageView.setBackgroundResource(R.drawable.refresh);
//使refreshImageView可点击
refreshImageView.setEnabled(true);
}
}
(2)searchcitycodeactivity.java
package com.example.weather;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Set;
import org.apache.http.params.HttpAbstractParamBean;
import org.apache.http.protocol.HTTP;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.ImageView;
public class SearchCityCodeActivity extends Activity {
private AutoCompleteTextView searchCityCodeAutoCompleteTextView;
private ImageView searchFinishImageView;
private HashMap<String, String> cityNameKeyCityCodeValueHashMap;
private Handler readXMLFinishHandler = new Handler() {
public void handleMessage(Message msg) {
setAutoCompleteTextViewAdapter();
}
private void setAutoCompleteTextViewAdapter() {
Set<String> cityNameSet = cityNameKeyCityCodeValueHashMap.keySet();
String[] cityNames = new String[cityNameSet.size()];
cityNameSet.toArray(cityNames);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
SearchCityCodeActivity.this,
android.R.layout.simple_list_item_1, cityNames);
searchCityCodeAutoCompleteTextView.setAdapter(adapter);
searchCityCodeAutoCompleteTextView.setThreshold(1);
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_city_code);
findViews();
setListener();
getCityCityCodeFromXML();
}
private void setListener() {
searchFinishImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String cityName = searchCityCodeAutoCompleteTextView.getText().toString().trim();
//异常处理
if (TextUtils.isEmpty(cityName)) {
searchCityCodeAutoCompleteTextView.setError("请输入城市名称");
return;
}
String cityCodeString = cityNameKeyCityCodeValueHashMap.get(cityName);
if (TextUtils.isEmpty(cityCodeString)) {
searchCityCodeAutoCompleteTextView.setError("没有此城市的相关信息");
return;
}
int cityCode = Integer.valueOf(cityCodeString);
setResult(cityCode);
finish();
}
});
}
private void getCityCityCodeFromXML() {
try {
// 先要把assets文件夹中的city_code.xml读取到代码中
final InputStream cityCityCodeInputStream = getAssets().open(
"city_code.xml");
// 解析XML文件是耗时性工作,所以要放到后台线程中去执行,而不是在主线程中
readCityCodeXML(cityCityCodeInputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
private void readCityCodeXMLFinish() {
Message message = new Message();
message.what = 100;
readXMLFinishHandler.sendMessage(message);
}
private void readCityCodeXML(final InputStream cityCityCodeInputStream) {
new Thread(new Runnable() {
@Override
public void run() {
try {
// 初始化hashMap对象
cityNameKeyCityCodeValueHashMap = new HashMap<String, String>();
// 创建解析器工厂
XmlPullParserFactory factory = XmlPullParserFactory
.newInstance();
// 解析器工厂生产解析器对象
XmlPullParser parser = factory.newPullParser();
// 给解析器对象配置数据流和数据编码方式
parser.setInput(cityCityCodeInputStream, HTTP.UTF_8);
// 先获取第一个标签的事件类型
int evenType = parser.getEventType();
// 循环判断标签是否为总的结束标签
while (evenType != XmlPullParser.END_TAG) {
if (evenType == XmlPullParser.START_TAG) {
// 获取当前标签的名字
String name = parser.getName();
// 如果标签的名字为key说明该标签的值为cityName
if (name.equals("key")) {
// 取到标签后的值指针移动到cityName
String cityNameKey = parser.nextText();
// 指针移动到</key>
parser.next();
// 指针移动到<string>
parser.next();
// 取到cityCode
String cityCodeValue = parser.nextText();
cityNameKeyCityCodeValueHashMap.put(
cityNameKey, cityCodeValue);
}
}
// 获取下个节点用于循环执行
parser.next();
// 获取下一个节点标签的事件类型用于判断是否结束循环
evenType = parser.getEventType();
}
readCityCodeXMLFinish();
System.out.println(cityNameKeyCityCodeValueHashMap
.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private void findViews() {
searchCityCodeAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.search_citycode_actv);
searchFinishImageView = (ImageView) findViewById(R.id.seach_finish_img);
}
}
(3)
package com.example.weather;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import android.text.TextUtils;
public class NetWorkUtils {
public static String doGet(String urlString){
String resultString = "";
StringBuffer stringBuffer = new StringBuffer();
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setConnectTimeout(10 * 1000);
connection.setReadTimeout(10 * 1000);
InputStream inputStream = connection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(
inputStream);
BufferedReader bufferedReader = new BufferedReader(
inputStreamReader);
String readLineString = bufferedReader.readLine();
while (!TextUtils.isEmpty(readLineString)) {
stringBuffer.append(readLineString);
readLineString = bufferedReader.readLine();
}
resultString = stringBuffer.toString();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return resultString;
}
}