zoukankan      html  css  js  c++  java
  • 基于百度定位及天气获取的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("
    weather:"); 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

  • 相关阅读:
    ZW网络团队及资源简介
    ZW云推客即将登场
    “4K云字库”基本框架图
    Sketch 55 Beta版本探秘,看看都有什么新功能
    产品经理有哪些类型?
    电影票APP原型设计分享– Movie Booking
    旅游类App的原型制作分享-Klook
    UI行业发展预测 & 系列规划的调整
    原来这就是 UI 设计师的门槛
    摹客PS插件全新改版!—— 智能检测不对应的设计稿
  • 原文地址:https://www.cnblogs.com/NeilLing/p/4263267.html
Copyright © 2011-2022 走看看