免费天气API Android实现(一)

要实现功能简述:1:通过对API接口的解析,首先实现全国所有城市的列表解析 API接口网址http://flash.weather.com.cn/wmaps/xml/china.xml 其中通过改变xml/后的参数实现省、市、县的获取。

2:通过API接口的解析,获取所要查询天气的信息

3:通过Service和BroadcastReceive 实现自动更新, 手动更新,前台通知功能。


首先构筑地域数据存储结构,此处采用Android内置的SQLite来实现:

代码如下:

首先建立省,市,县类。代码类似,提供一个:

import java.io.Serializable;


public class City implements Serializable{
private int id;
private String cityName;
private String cityCode;
private int provinceId;

public int getId(){
return id;
}

public void setId(int id){
this.id = id;
}

public String getCityName(){
return cityName;
}

public void setCityName(String cityName){
this.cityName = cityName;
}

public String getCityCode(){
return cityCode;
}

public void setCityCode(String cityCode){
this.cityCode = cityCode;
}

public int getProvinceId(){
return provinceId;
}

public void setProvinceId(int provinceId){
this.provinceId = provinceId;
}
}


创建SQLite table:

public class MyWeatherOpenHelper extends SQLiteOpenHelper {
public static final String CREAT_PROVINCE = "create table Province (" + "id integer primary key autoincrement," + "province_name text,"
+"province_code text)";
public static final String CREAT_CITY = "create table City (" + "id integer primary key autoincrement," + "city_name text,"
+"city_code text," + "province_id integer)";
public static final String CREAT_COUNTY = "create table County (" + "id integer primary key autoincrement," + "county_name text,"
+"county_code text," +"city_id integer)";
public MyWeatherOpenHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}


@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREAT_PROVINCE);
db.execSQL(CREAT_CITY);
db.execSQL(CREAT_COUNTY);

}


@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

}

创建城市类别加载和处理部分:

public class MyWeatherDB {
public static final  String DB_NAME = "my_weather";
public static final int VERSION =1;
private  static MyWeatherDB myWeatherDB;
public SQLiteDatabase db;
/*
* 将构造方法私有化 只可以从getInstance方法获得MyWeatherDB类
*/
private MyWeatherDB(Context context){
MyWeatherOpenHelper dbHelper = new MyWeatherOpenHelper(context, DB_NAME, null, 1);
db =dbHelper.getWritableDatabase();
}

/*
 *get the MyWeather example  
 */
public synchronized static MyWeatherDB getInstance(Context context){
if(myWeatherDB == null)
myWeatherDB = new MyWeatherDB(context);
return myWeatherDB;
}
/*分别开始创建 省、市、县的存储和加载函数,操作为SQLite插入和查询操作

/*
* read province information
*/
public List<Province> loadProvince(){
List<Province> list = new ArrayList<Province>();
Cursor cursor = db.query("Province", null, null, null, null, null, null);
if(cursor.moveToFirst()){
do{
Province province = new Province();
province.setId(cursor.getInt(cursor.getColumnIndex("id")));
province.setProvinceName(cursor.getString(cursor.getColumnIndex("province_name")));
province.setProvinceCode(cursor.getString(cursor.getColumnIndex("province_code")));
list.add(province);
}while(cursor.moveToNext());
}
return list;
}

/*
* save the city
*/
public void saveCity(City city){
if(city !=null){
ContentValues values = new ContentValues();
values.put("city_name", city.getCityName());
values.put("city_code", city.getCityCode());
values.put("province_id", city.getProvinceId());
db.insert("City", null, values);
}
}
/*
* read city information
*/
public List<City> loadCity(int provinceId){
List<City> list = new ArrayList<City>();
Cursor cursor = db.query("City", null, "province_id = ?" , new String[] {String.valueOf(provinceId)}, null, null, null);
if(cursor.moveToFirst()){
do{
City city = new City();
city.setId(cursor.getInt(cursor.getColumnIndex("id")));
city.setCityName(cursor.getString(cursor.getColumnIndex("city_name")));
city.setCityCode(cursor.getString(cursor.getColumnIndex("city_code")));
city.setProvinceId(provinceId);
list.add(city);
}while(cursor.moveToNext());
}
return list;
}
/*
* save county
*/
public void saveCounty(County county){
if(county != null){
ContentValues values = new ContentValues();
values.put("county_name", county.getCountyName());
values.put("county_code", county.getCountyCode());
values.put("city_id", county.getCityId());
db.insert("County", null, values);
}
}
/*
* read county information
*/
public List<County> loadCounty(int cityId){
List<County> list = new ArrayList<County>();
Cursor cursor = db.query("County", null,"city_id = ?", new String[]{String.valueOf(cityId)}, null, null, null);
if(cursor.moveToFirst()){
do{
County county = new County();
county.setId(cursor.getInt(cursor.getColumnIndex("id")));
county.setCountyName(cursor.getString(cursor.getColumnIndex("county_name")));
county.setCountyCode(cursor.getString(cursor.getColumnIndex("county_code")));
county.setCityId(cityId);
list.add(county);
}while(cursor.moveToNext());
}
return list;
}
}

至此,关于地域的框架已经构建完成,实现了省、市、县3级的本地存储和加赞功能

下一步,考虑如何从网上解析到有关城市的信息。本例中采用了HttpURLConnection方式在从网络加载信息。

代码如下:

public class HttpUtil {
public static void sendHttpRequest(final String address , final HttpCallbackListener listener){
new Thread(new Runnable(){


@Override
public void run() {
HttpURLConnection connection = null;
try{
URL url = new URL(address);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while((line = reader.readLine())!=null){
response.append(line);
}
if(listener!= null){
listener.onFinish(response.toString());
}
}catch(Exception e){
if(listener != null){
listener.onError(e);
}
}finally{
if(connection != null){
connection.disconnect();
}
}
}

}).start();
}
}

因为,本例中所使用的API接口是XML格式的文件,所以针对此处的情况,要对xml格式进行解析。

代码如下(只提供了省的,关于市和县的j):

public class ProvincePullXml {
List<Province> provinces = new ArrayList<Province>();
String result="";
public String paresXMLWithPull(String xmlData){
try{
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser xmlPullParser = factory.newPullParser();
xmlPullParser.setInput(new StringReader(xmlData));
int eventType = xmlPullParser.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
switch(eventType){
case XmlPullParser.START_TAG: 
String name = xmlPullParser.getName();
if("city".equals(name)){
Province province = new Province();
province.setProvinceName(xmlPullParser.getAttributeValue(null, "quName"));
province.setProvinceCode(xmlPullParser.getAttributeValue(null, "pyName"));
provinces.add(province);
}
break;
case XmlPullParser.END_TAG:
break;
default:break;
}
eventType = xmlPullParser.next();
}
}catch(Exception e){
e.printStackTrace();
}
for(Province province:provinces){
result += province.getProvinceCode()+"|"+province.getProvinceName()+",";
}
return result;
}
}

解析之后接着是存储和处理 具体代码如下:

public class Utility {
/*
* Data processing
*/
public synchronized static boolean handleProvincesResponse(MyWeatherDB myWeatherDB , String response){
if(!TextUtils.isEmpty(response)){
String[] allProvinces = response.split(",");
if(allProvinces != null && allProvinces.length >0){
for(String p:allProvinces){
String[] array = p.split("\\|");
Province province = new Province();
province.setProvinceCode(array[0]);
province.setProvinceName(array[1]);
myWeatherDB.saveProvince(province);
}
return true;
}
}
return false;
}

public static boolean handleCitiesResponse(MyWeatherDB myWeatherDB , String response , int provinceId){
if(!TextUtils.isEmpty(response)){
String[] allCities = response.split(",");
if(allCities != null &&allCities.length >0){
for(String c : allCities){
String[] array = c.split("\\|");
City city = new City();
city.setCityCode(array[0]);
city.setCityName(array[1]);
city.setProvinceId(provinceId);
myWeatherDB.saveCity(city);
}
return true;
}
}
return false;
}

public static boolean handleCountiesResponse(MyWeatherDB myWeatherDB, String response , int cityId){
if(!TextUtils.isEmpty(response)){
String[] allCounties = response.split(",");
if(allCounties != null && allCounties.length >0){
for(String c : allCounties){
String[] array = c.split("\\|");
County county = new County();
county.setCountyCode(array[0]);
county.setCountyName(array[1]);
county.setCityId(cityId);
myWeatherDB.saveCounty(county);
}
return true;
}
}
return false;
}
}

到此所有的准备工作都已经做完,稍微总结一下:第一步创建类,数据库 第二步 完成对数据的存储和提取 第三部完成网上数据的读取、解析、 处理 。

开始关于城市选择的Activity;

具体代码如下:

public class ChooseAreaActivity extends Activity {
public static final int LEVEL_PROVINCE = 0;
public static final int LEVEL_CITY = 1;
public static final int LEVEL_COUNTY =2;

private ProgressDialog progressDialog;
private TextView titleText;
private ListView listView;
private ArrayAdapter<String> adapter;
private MyWeatherDB myWeatherDB;
private List<String> datalist = new ArrayList<String>();
private List<Province> provinceList;
private List<City> cityList;
private List<County> countyList;
private Province selectedProvince;
private City selectedCity;
private County selectedCounty;
private int currentLevel;
public final static int RESULT_CODE=1; 
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.choose_area);
listView = (ListView)findViewById(R.id.list_view);
titleText = (TextView)findViewById(R.id.title_text);
adapter = new ArrayAdapter<String>(this , android.R.layout.simple_list_item_1, datalist);
listView.setAdapter(adapter);
myWeatherDB = MyWeatherDB.getInstance(this);


listView.setOnItemClickListener(new OnItemClickListener(){


@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if(currentLevel == LEVEL_PROVINCE){
selectedProvince = provinceList.get(position);
queryCity();
}else if(currentLevel == LEVEL_CITY){
selectedCity = cityList.get(position);
queryCounty();
}else if(currentLevel == LEVEL_COUNTY){
selectedCounty = countyList.get(position);
Intent intent = new Intent();
intent.putExtra("SelectedCounty", selectedCounty);
intent.putExtra("SelectedCity", selectedCity);
setResult(RESULT_CODE , intent);
finish();
}
}

});
queryProvince();
}

/*
* search province from SQLite first then from Internet
*/
private void queryProvince(){
provinceList = myWeatherDB.loadProvince();
if(provinceList.size() > 0){
datalist.clear();
for(Province province : provinceList){
datalist.add(province.getProvinceName()+"  "+ province.getProvinceCode());
}
adapter.notifyDataSetChanged();
listView.setSelection(0);
titleText.setText("中国");
currentLevel = LEVEL_PROVINCE;
}else{
queryFromServer(null , "province");
}
}
/*
* search city from SQLite first then from Internet
*/
private void queryCity(){
cityList = myWeatherDB.loadCity(selectedProvince.getId());
if(cityList.size()>0){
datalist.clear();
for(City city:cityList){
datalist.add(city.getCityName() + "  " + city.getCityCode());
}
adapter.notifyDataSetChanged();
listView.setSelection(0);
titleText.setText(selectedProvince.getProvinceName());
currentLevel = LEVEL_CITY;
}else{
queryFromServer(selectedProvince.getProvinceCode() , "city");
}
}

private void queryCounty(){
countyList = myWeatherDB.loadCounty(selectedCity.getId());
if(countyList.size() > 0){
datalist.clear();
for(County county : countyList){
datalist.add(county.getCountyName() + "   " + county.getCountyCode());
}
adapter.notifyDataSetChanged();
listView.setSelection(0);
titleText.setText(selectedCity.getCityName());
currentLevel = LEVEL_COUNTY;
}else{
queryFromServer(selectedCity.getCityCode(), "county");
}
}

private void queryFromServer(final String code , final String type){
String address;
if(!TextUtils.isEmpty(code)){
address = "http://flash.weather.com.cn/wmaps/xml/" + code+".xml";
}else{
address = "http://flash.weather.com.cn/wmaps/xml/china.xml";
}
showProgressDialog();
HttpUtil.sendHttpRequest(address, new HttpCallbackListener(){


@Override
public void onFinish(String response) {
boolean result = false;
if("province".equals(type)){
ProvincePullXml provincePullXml = new ProvincePullXml();
result = Utility.handleProvincesResponse(myWeatherDB, provincePullXml.paresXMLWithPull(response));
}else if("city".equals(type)){
CityPullXml cityPullXml = new CityPullXml();
result = Utility.handleCitiesResponse(myWeatherDB, cityPullXml.paresXMLWithPull(response), selectedProvince.getId());
}else if("county".equals(type)){
CountyPullXml countyPullXml = new CountyPullXml();
result = Utility.handleCountiesResponse(myWeatherDB, countyPullXml.paresXMLWithPull(response), selectedCity.getId());
}
if(result){
runOnUiThread(new Runnable(){


@Override
public void run() {
closeProgressDialog();
if("province".equals(type)){
queryProvince();
}else if("city".equals(type)){
queryCity();
}else if("county".equals(type)){
queryCounty();
}
}
});
}
}


@Override
public void onError(Exception e) {
runOnUiThread(new Runnable(){


@Override
public void run() {
closeProgressDialog();
Toast.makeText(ChooseAreaActivity.this, "加载失败", Toast.LENGTH_SHORT).show();
}

});
}

});
}

private void showProgressDialog(){
if(progressDialog == null){
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("正在加载...");
// progressDialog.setCancelable(false);
}
progressDialog.show();
}

private void closeProgressDialog(){
if(progressDialog != null)
progressDialog.dismiss();
}


@Override
public void onBackPressed() {
if(currentLevel == LEVEL_COUNTY){
queryCity();
}else if (currentLevel == LEVEL_CITY){
queryProvince();
}else{
finish();
}
}
}

通过三层ListVIew完成显示。如果本地有数据就从本地加载,如果没有就从网络加载,加载时,显示progressDialog来提示加载过程:

至此第一步全部完成,关于城市加载任务.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值