基于百度定位及天气获取的DEMO

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处理:

handler异步多线程执行步骤(非UI线程发送消息到UI线程分为3个步骤)

   1.message.sendToTarget()方法把这条message放到消息队列中去。

   Runnable runnable = new Runnable()

  {

              @Override 

              public void run() {// run()在新的线程中运行

  

            sb.append("\nweather:"); sb.append(new GetWeather().getWeather(

           location.getDistrict().substring(0, location.getDistrict().length()

            - 1)) .getSuggestion());//获取基本出行建议

            mHandler.obtainMessage(MSG_SUCCESS, sb.toString())

           .sendToTarget();// 获取成功,将定位信息和异步获取的出行建议存入messagem,向ui线程发送 

        } 

          };

   2.定义更新UI

    private Handler mHandler = new Handler() {

            public void handleMessage(Message msg) {// 此方法在ui线程运行

                switch (msg.what) {

                case MSG_SUCCESS:

                    logMsg((String) msg.obj);//根据第一步发送来的message的信息,将msg.obj(定位信息和出行信息)显示在textview中。

                    break;

                default:

                    logMsg("查询失败");

                    break;

                }

            }

        };

    3.在主线程中启动thread

    if (mThread == null) {

                mThread = new Thread(runnable);

                mThread.start();// 线程启动

            }

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传入的参数。

关键代码1(传递 单一String 字段):

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() {

        

    }



    @Override

    protected String doInBackground(Object... params) {

        return new Weather().getWeather((String)params[0]);//真正的异步工作,从服务器获取xml数据并解析,但不能对UI操作

    

    }



    protected void onPostExecute(String result) {

        // 该方法运行在UI线程内,更新UI

        tv.setText(result);



    }



}

UI主线程调用

//注意:1)LoadWeatherAsyncTask 的实例必须在UI thread中创建 2) execute方法必须在UI thread中调用 
LoadWeatherAsyncTask lwa = new LoadWeatherAsyncTask(weatherInfo);

                //将parcelableInfo.getCity()变量传入LoadWeatherAsyncTask.java中doInBackground方法中

                lwa.execute(parcelableInfo.getCity());

 

附:传递JavaBean对象

public class LoadWeatherAsyncTask extends AsyncTask<Object, Integer, WeatherInfo> {



    private TextView tv;



    //表明对哪个textview进行异步更新

    public LoadWeatherAsyncTask(TextView tv) {

        this.tv = tv;

    }



    //准备工作,一般初始化textview

    @Override

    protected void onPreExecute() {

        

    }



    //注意:1) Task的实例必须在UI thread中创建  2) execute方法必须在UI thread中调用 )

    @Override

    protected WeatherInfo doInBackground(Object... params) {

        // TODO Auto-generated method stub

        System.out.println((String)params[0]);

        return new GetWeather().getWeather((String)params[0]);//该处返回的结果作为onPostExecute(WeatherInfo result)的rusult参数
} protected void onPostExecute(WeatherInfo result) { // 该方法运行在UI线程内  tv.setText(result.getSuggestion()); } }

 

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());

 5.获取和XML解析和JSON解析

a.JSON

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.UnsupportedEncodingException;

import java.net.URL;

import java.net.URLConnection;

import java.net.URLEncoder;



import org.json.JSONException;

import org.json.JSONObject;





public class GetWeather {



    String StrUrl;

    public WeatherInfo getWeather(String cityName) 

 {

        StringBuffer strBuf = new StringBuffer();  

        WeatherInfo weatherInfo=new WeatherInfo();

         

        //访问URL获取JSON

        String StrUrl = null;

        try {

            StrUrl = "http://api.map.baidu.com/telematics/v3/weather?location="+URLEncoder.encode(cityName, "utf-8")+"&output=json&ak=NtQaBbYDC2kn89KENQhFM2o5";

        } catch (UnsupportedEncodingException e1) {

            // TODO Auto-generated catch block

            e1.printStackTrace();

        }

        

        System.out.println(StrUrl);

    

          try{

            URL url=new URL(StrUrl);

            URLConnection conn = url.openConnection();  

            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));//转码。  

            String line = null;  

            while ((line = reader.readLine()) != null)  

                strBuf.append(line);  

                reader.close();  

        }catch(Exception e){  

            e.printStackTrace();   

        }     



        String getStr=strBuf.toString();

        System.out.println("JSON数据打印:  "+getStr);

        

        try{

            // 将json字符串转换为json对象

            JSONObject jsonObj = new JSONObject(getStr);

            // 得到指定json key对象的value对象



              //获取当前城市

              JSONObject mainArr=jsonObj.getJSONArray("results").getJSONObject(0);  

              weatherInfo.setCity(mainArr.getString("currentCity"));

              

              //获取PM2.5信息

              weatherInfo.setPM25(mainArr.getString("pm25"));

              

              JSONObject weatherData=jsonObj.getJSONArray("results").getJSONObject(0).getJSONArray("weather_data").getJSONObject(0);

             //获取实时时间

              weatherInfo.setTime(weatherData.getString("date"));

              // 获取基本天气属性simpleweather

              weatherInfo.setSimpleweather(weatherData.getString("weather"));

              //获取温度

              weatherInfo.setTemperature(weatherData.getString("temperature"));

              //获取出行建议

              JSONObject weatherSuggetion=jsonObj.getJSONArray("results").getJSONObject(0).getJSONArray("index").getJSONObject(0);

              weatherInfo.setSuggestion(weatherSuggetion.getString("des"));

        }catch (JSONException e)

        {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        return weatherInfo;

    }

}

b.xml(也可以返回javaBean对象,这里只考虑返回String变量)

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;



public class Weather {



    static int[] day = { 0, 1, 2, 3, 4 };

    static String weather;

    static String high;

    static String low;

    int SECCESS = 1;

    int FAIL = 0;



    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;

    }

}

本人初学上路,语言表达不准确,见谅···

第一版XML源码地址:http://download.csdn.net/detail/xiejun1026/8411437

第二版JSON源码下载地址:http://download.csdn.net/detail/xiejun1026/8413329

 

你可能感兴趣的:(demo)