基於百度定位及天氣獲取的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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM