YOU'VE ENTERED A SIMPLE ANDROIDBLOG, WELCOME.

Develop And Improve。

极简天气开发日记Day03

Things have done

今天完成了省市县列表的构建,以及定位功能的实现。首先在activity包下新建了ChooseAreaActivity活动负责构建城市选择列表,在layout文件夹下新建choose_area.xml对应此活动布局,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#3CA9C4">

<TextView
android:id="@+id/title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="#fff"
android:textSize="24sp"/>
</RelativeLayout>
<Button
android:id="@+id/locate"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="@drawable/locate"
android:layout_marginLeft="5dp"
/>
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent">

</ListView>
</LinearLayout>

很简单的一个布局,最上方TextView显示当前地域信息充当标题栏,下方一个Button用来定位,Button底下ListView负责显示省市县内容。

城市选择列表实现

在ChooseAreaActivity中首先定义以及绑定控件,通过ListView点击事件判断当前层次进而执行相应的查询函数

1
2
3
4
5
6
7
8
9
10
11
12
13
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(currentLevel==LEVEL_PROVINCE){
selectedProvince=provinceList.get(position);
queryCities();
}else if(currentLevel==LEVEL_CITY){
selectedCity=cityList.get(position);
queryCounties();
}
}
});
queryProvinces();

三个query函数基本相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* query Province from database or server
*/

private void queryProvinces(){
provinceList=weatherDB.loadProvinces();
if(provinceList.size()>0){
dataList.clear();
for(Province province:provinceList){
dataList.add(province.getProvinceName());
}
adapter.notifyDataSetChanged();
listView.setSelection(0);
titleText.setText("中国");
currentLevel=LEVEL_PROVINCE;
}else{
queryFromServer(null,"province");
}
}

首先从数据库查询省,如果数据为空则调用queryFromServer函数从服务器查询相应信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* query from server
*/

private void queryFromServer(final String code,final String type){
String address;
if(!TextUtils.isEmpty(code)){
address="http://www.weather.com.cn/data/list3/city"+code+".xml";
}else{
address="http://www.weather.com.cn/data/list3/city.xml";
}
showProgressDialog();
HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {
@Override
public void onFinish(String response) {
boolean result=false;
if("province".equals(type)){
result= Utility.handleProvincesResponse(weatherDB,response);
}else if("city".equals(type)){
result=Utility.handlCitiesResponse(weatherDB,response,selectedProvince.getId());
}else if("county".equals(type)){
result=Utility.handleCountiesResponse(weatherDB,response,selectedCity.getId());
}
if(result){
runOnUiThread(new Runnable() {
@Override
public void run() {
closeProgressDialog();
if("province".equals(type)){
queryProvinces();
}else if("city".equals(type)){
queryCities();
}else if("county".equals(type)){
queryCounties();
}
}
});
}
}

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

在这个函数里调用了封装在工具包里的处理Response的几个函数将数据存储到数据库,由于只能在主线程里更新UI,所以调用runOnUiThread来回调相应query函数更新UI,这样就实现了省市县三级列表。

定位功能实现

首先按图所示导入相应jar包并添加依赖

http://pic.yupoo.com/333ddd/FPg5yZGp/gsVQo.png

在util包下新建LocationApplication类负责定位功能,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class LocationApplication extends Application {
public LocationClient mLocationClient;//定位SDK的核心类
public MyLocationListener mMyLocationListener;//定义监听类

@Override
public void onCreate() {
super.onCreate();
mLocationClient = new LocationClient(this.getApplicationContext());
mMyLocationListener = new MyLocationListener();
mLocationClient.registerLocationListener(mMyLocationListener);
}

/**
* 实现实位回调监听
*/

public class MyLocationListener implements BDLocationListener {

public void onReceiveLocation(BDLocation location) {
//Receive Location
StringBuffer sb = new StringBuffer(256);
// sb.append("\nerror code : ");
// sb.append(location.getLocType());//获得erro code得知定位现状
if (location.getLocType() == BDLocation.TypeGpsLocation){//通过GPS定位
// sb.append("\n地址为 : ");
sb.append(location.getAddrStr());//获得当前地址
// sb.append(location.getDirection());//获得方位
} else if (location.getLocType() == BDLocation.TypeNetWorkLocation){//通过网络连接定位
// sb.append("\n地址为 : ");
sb.append(location.getAddrStr());//获得当前地址
}
Toast.makeText(getApplicationContext(),"Address:"+location.getAddrStr(),Toast.LENGTH_SHORT).show();
mLocationClient.stop();
}
}
}

百度定位SDK可提供相当多的回馈信息,这里我是在官方提供的示例代码下进行了部分修改最终只获得地理位置信息

在做这个时候浪费了很多时间,因为百度定位SDK无法在虚拟机下成功运行,所以我在调试时候一直返回错误码167,即服务端定位失败,后来在官方论坛才发现只能在真机下调试定位功能

同时在util包下使用了百度demo中提供的Utils类储存了错误码对应的原因

在ChooseAreaActivity类中为定位按钮添加了点击事件,并写了getLocation()方法获得定位信息

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* start location
*/

private void getLocation() {
mLocationClient = ((LocationApplication)getApplication()).mLocationClient;
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);//设置高精度定位定位模式
option.setCoorType("bd09ll");//设置百度经纬度坐标系格式
option.setScanSpan(1000);//设置发起定位请求的间隔时间为1000ms
option.setIsNeedAddress(true);//反编译获得具体位置,只有网络定位才可以
mLocationClient.setLocOption(option);
mLocationClient.start();
}

到这里只是通过Toast来调试定位功能是否正常,后续代码还需要对回馈信息处理只获得天气Api中所需的内容

Things to do

解析Api返回的JSON数据,不知道如何将多层JSON数组解析成单层的,对于下面这段JSON数据也不知道如何取出拥有同一名称的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"HeWeather data service 3.0": [
{

"status": "ok", //接口状态,参考http://www.heweather.com/documents/api

"basic": { //基本信息
"city": "北京", //城市名称
"cnty": "中国", //国家
"id": "CN101010100", //城市ID,参见http://www.heweather.com/documents/cn-city-list
"lat": "39.904000", //城市维度
"lon": "116.391000", //城市经度
"update": { //更新时间
"loc": "2015-07-02 14:44", //当地时间
"utc": "2015-07-02 06:46" //UTC时间
}
},

"now": { //实况天气
"cond": { //天气状况
"code": "100", //天气状况代码
"txt": "晴" //天气状况描述
},
"fl": "30", //体感温度
"hum": "20%", //相对湿度(%)
"pcpn": "0.0", //降水量(mm)
"pres": "1001", //气压
"tmp": "32", //温度
"vis": "10", //能见度(km)
"wind": { //风力风向
"deg": "10", //风向(360度)
"dir": "北风", //风向
"sc": "3级", //风力
"spd": "15" //风速(kmph)
}
},

"aqi": { //空气质量,仅限国内部分城市,国际城市无此字段
"city": {
"aqi": "30", //空气质量指数
"co": "0", //一氧化碳1小时平均值(ug/m3)
"no2": "10", //二氧化氮1小时平均值(ug/m3)
"o3": "94", //臭氧1小时平均值(ug/m3)
"pm10": "10", //PM10 1小时平均值(ug/m3)
"pm25": "7", //PM2.5 1小时平均值(ug/m3)
"qlty": "优", //空气质量类别
"so2": "3" //二氧化硫1小时平均值(ug/m3)
}
},

"daily_forecast": [ //7天天气预报
{
"date": "2015-07-02", //预报日期
"astro": { //天文数值
"sr": "04:50", //日出时间
"ss": "19:47" //日落时间
},
"cond": { //天气状况
"code_d": "100", //白天天气状况代码,参考http://www.heweather.com/documents/condition-code
"code_n": "100", //夜间天气状况代码
"txt_d": "晴", //白天天气状况描述
"txt_n": "晴" //夜间天气状况描述
},
"hum": "14", //相对湿度(%)
"pcpn": "0.0", //降水量(mm)
"pop": "0", //降水概率
"pres": "1003", //气压
"tmp": { //温度
"max": "34℃", //最高温度
"min": "18℃" //最低温度
},
"vis": "10", //能见度(km)
"wind": { //风力风向
"deg": "339", //风向(360度)
"dir": "东南风", //风向
"sc": "3-4", //风力
"spd": "15" //风速(kmph)
}
},
...... //略

],
"hourly_forecast": [ //每三小时天气预报,全能版为每小时预报
{
"date": "2015-07-02 01:00", //时间
"hum": "43", //相对湿度(%)
"pop": "0", //降水概率
"pres": "1003", //气压
"tmp": "25", //温度
"wind": { //风力风向
"deg": "320", //风向(360度)
"dir": "西北风", //风向
"sc": "微风", //风力
"spd": "12" //风速(kmph)
}
},
...... //略

],


}


比较迷…..