demo基于百度定位APIv4.0版、新浪天气(不用查询城市代码)。
需求:
1、button实现触发定位监听和天气捕获
2、两个textview 分别显示详细地址、天气。
界面很简陋,侧重功能实现。
下面记录下主要技术点:
1.百度定位
/** * 发起定位 */ public void requestLocationInfo() { setLocationOption(); if (mLocationClient != null && !mLocationClient.isStarted()) { mLocationClient.start(); } if (mLocationClient != null && mLocationClient.isStarted()) { mLocationClient.requestLocation(); } } /** * 设置相关参数 */ private void setLocationOption() { LocationClientOption option = new LocationClientOption(); option.setOpenGps(true); // 打开gps option.setCoorType("bd09ll"); // 设置坐标类型 option.setServiceName("com.baidu.location.service_v2.9"); option.setPoiExtraInfo(true); option.setAddrType("all"); option.setPoiNumber(10); option.disableCache(true); mLocationClient.setLocOption(option); } /** * 监听函数,有更新位置的时候,格式化成字符串,输出到屏幕中 */ public class MyLocationListenner implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { if (location == null) { sendBroadCast(new ParcelableInfo("获取失败","获取失败")); return; } address=location.getAddrStr(); } public void onReceivePoi(BDLocation poiLocation) { if (poiLocation == null) { sendBroadCast(new ParcelableInfo("获取失败","获取失败")); return; } sendBroadCast(new ParcelableInfo(poiLocation.getDistrict(),poiLocation.getAddrStr())); } }
2.异步获取天气信息
异步多线程一般处理方式有;1.handler处理:后续补充
2、AsyncTask:AsyncTask能够更恰当和更简单的去使用UI线程。这个类允许执行后台操作和展现结果在UI线程上,无需操纵线程和/或处理程序。AsyncTask的内部实现是一个线程池,每个后台任务会提交到线程池中的线程执行,然后使用Thread+Handler的方式调用回调函数。
使用AsyncTask类,以下是几条必须遵守的准则:
1) Task的实例必须在UI thread中创建
2) execute方法必须在UI thread中调用
3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法
4) 该task只能被执行一次,否则多次调用时将会出现异常
doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。
关键代码:
package com.liucanwen.baidulocation; /* * 异步多线程加载网络信息,并更新UI * 通常有两种方法:1、handler和Threat * 2、AsyncTask * 参考网址 http://www.cnblogs.com/dawei/archive/2011/04/18/2019903.html */ import java.net.URL; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.liucanwen.baidulocation.util.UTF82GBK; import com.liucanwen.baidulocation.util.Weather; import android.os.AsyncTask; import android.widget.TextView; public class LoadWeatherAsyncTask extends AsyncTask<Object, Integer, String> { private TextView tv; String getweather; //表明对哪个textview进行异步更新 public LoadWeatherAsyncTask(TextView tv) { this.tv = tv; } //准备工作,一般初始化textview @Override protected void onPreExecute() { } //注意:1) Task的实例必须在UI thread中创建 2) execute方法必须在UI thread中调用 ) @Override protected String doInBackground(Object... params) { return new Weather().getWeather((String)params[0]);//真正的异步工作,从服务器获取xml数据并解析,但不能对UI操作 } protected void onPostExecute(String result) { // 该方法运行在UI线程内 tv.setText(result); } }
3.困扰好几天的编码问题导致返回天气数据为null
由于之前直接将“广州“的UTF8编码传入URL(ADT默认编码UTF8)导致获取不到天气数据,
URL ur = new URL("http://php.weather.sina.com.cn/xml.php?city=" + str+ "&password=DJOYnieT8234jlsK&day=" + day);
后来发现,传入的str需要为GB2312编码数据。所以需要转码
new UTF82GBK().getCoding(str)
public String getCoding(String str) throws IOException{ String s1 = URLEncoder.encode(str, "gb2312"); return s1; }
public String getWeather(String str) { try { DocumentBuilderFactory domfac = DocumentBuilderFactory .newInstance(); DocumentBuilder dombuilder = domfac.newDocumentBuilder(); Document doc; Element root; NodeList books; // 浏览器中识别的是GBK编码,直接输入汉字是接收不到数据的 URL ur = new URL("http://php.weather.sina.com.cn/xml.php?city=" + new UTF82GBK().getCoding(str) + "&password=DJOYnieT8234jlsK&day=" + day); // 解析XML doc = (Document) dombuilder.parse(ur.openStream()); root = (Element) doc.getDocumentElement(); books = ((Node) root).getChildNodes(); for (Node node = books.item(1).getFirstChild(); node != null; node = node .getNextSibling()) { if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getNodeName().equals("status1")) weather = node.getTextContent(); // 获取天气状况 else if (node.getNodeName().equals("temperature1")) high = node.getTextContent(); // 获取最高温度 else if (node.getNodeName().equals("temperature2")) low = node.getTextContent(); // 获取最低温度 } } } catch (Exception e) { e.getMessage(); } String getweather = str + " " + weather + " " + low + "度~" + high + "度"; return getweather; }
4.Intent传递对象
需要从传入MyApplication将City和address传入到MainActivity中,将需要传递的数据封装到LocationInfo类中。
使用intent传递对象的方法有两种:
1、实现Serializable接口
2、实现Parcelable接口
我采用 实现Parcelable接口:
LocationInfo .java用于确定传递数据的数据模型
public class LocationInfo implements Serializable { private String city; private String address; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
/** * 实现了Parcelable接口的ParcelableInfo类: */ import android.os.Parcel; import android.os.Parcelable; public class ParcelableInfo implements Parcelable { private String city; private String address; public ParcelableInfo() { } public ParcelableInfo(String city, String address) { this.city = city; this.address = address; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public static final Parcelable.Creator<ParcelableInfo> CREATOR = new Creator<ParcelableInfo>() { @Override public ParcelableInfo createFromParcel(Parcel source) { ParcelableInfo parcelableInfo = new ParcelableInfo(); parcelableInfo.city = source.readString(); parcelableInfo.address = source.readString(); return parcelableInfo; } @Override public ParcelableInfo[] newArray(int size) { return new ParcelableInfo[size]; } }; @Override public int describeContents() { // TODO Auto-generated method stub return 0; } @Override public void writeToParcel(Parcel dest, int flags) { // TODO Auto-generated method stub dest.writeString(city); dest.writeString(address); } }
public void sendBroadCast(ParcelableInfo parcelableInfo) { stopLocationClient(); Intent intent = new Intent(MainActivity.LOCATION_BCR); //ParcelableInfo parcelableUser = new ParcelableInfo(city,address); //intent.putExtra("address", address); Bundle bundle = new Bundle(); bundle.putParcelable("parcelableInfo", parcelableInfo); intent.putExtras(bundle); sendBroadcast(intent); }
在MyApplication中发送
public void sendBroadCast(ParcelableInfo parcelableInfo) { stopLocationClient(); Intent intent = new Intent(MainActivity.LOCATION_BCR); Bundle bundle = new Bundle(); bundle.putParcelable("parcelableInfo", parcelableInfo); //将parcelableInfo对象封装在bundle中 intent.putExtras(bundle); //intent传递bundle sendBroadcast(intent); }
在MainActivity中接收
parcelableInfo = intent.getParcelableExtra("parcelableInfo"); locInfo.setText("你所在的地址为:" + parcelableInfo.getAddress());
本人初学上路,语言表达不准确,见谅···
源码地址:http://download.csdn.net/detail/xiejun1026/8411437