*****
**WebService簡介及實戰**
[TOC=6]
# 1. WebService簡介
簡單來說Web Service就是某個站點開放出來的數據服務。
Web service是一個平臺獨立的,低耦合的,自包含的、基于可編程的web的應用程序,可使用開放的XML(標準通用標記語言下的一個子集)標準來描述、發布、發現、協調和配置這些應用程序,用于開發分布式的互操作的應用程序。
(1)SOAP協議:
SOAP協議的概念:簡單的對象訪問協議,是一種輕量型,簡單,基于XML協議,它被設計成在WEB上交換結構化的和固化的信息;
SOAP協議組成部分:
* SOAP封裝:定義了一個框架(描述信息的多少,誰發送,誰接受,誰處理,怎么處理等信息);
* SOAP編碼規則:定義了可選數據編碼規則;
* SOAP RPC表示:定義一個遠程調用風格信息交換的模式;
* SOAP綁定:定義了SOAP和HTTP之間綁定和使用的底層協議的交換;
(2)WSDL:
Web Service描述語言WSDL 就是用機器能閱讀的方式提供的一個正式描述文檔而基于XML(標準通用標記語言下的一個子集)的語言,用于描述Web Service及其函數、參數和返回值。因為是基于XML的,所以WSDL既是機器可閱讀的,又是人可閱讀的。
# 2. Webservice 實戰 天氣預報

## 2.1 需求:
* 選擇省份--城市聯動
* 選擇城市--天氣聯動
* 顯示5天天氣
## 2.2 代碼實現
WebService使用注意點:
1.創建HttpTransportSE傳輸對象:
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
SERVICE_URL是webservice提供服務的url
2.使用SOAP1.1協議創建Envelop對象:
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
設置SOAP協議的版本號,根據服務端WebService的版本號設置。
3.實例化SoapObject對象:
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName);
第一個參數表示WebService的命名空間,可以從WSDL文檔中找到WebService的命名空間。第二個參數表示要調用的WebService方法名。
4.設置調用方法的參數值,如果沒有參數,可以省略:例如
soapObject.addProperty("theCityCode", cityName);
5.記得設置bodyout屬性 envelope.bodyOut = soapObject;
6.調用webservice:ht.call(SERVICE_NAMESPACE+methodName, envelope);
7.獲取服務器響應返回的SOAP消息:
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName+"Result");
### 2.2.1 WebServiceUtil代碼
`
~~~
package cn.zhaoliang5156.demo;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* WebService 工具類
* @author zhaoliang
* @version 1.0
*/
public class WebServiceUtil {
// 定義webservice的命名空間
public static final String SERVICE_NAMESPACE = "http://WebXml.com.cn/";
// 定義webservice提供服務的url
public static final String SERVICE_URL = "http://ws.webxml.com.cn/WebServices/WeatherWS.asmx";
// 調用遠程webservice獲取省份列表
public static List<String> getProvinceList() {
// 調用 的方法
String methodName = "getRegionProvince";
// 創建HttpTransportSE傳輸對象
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
try {
ht.debug = true;
// 使用SOAP1.1協議創建Envelop對象
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
// 實例化SoapObject對象
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE,
methodName);
envelope.bodyOut = soapObject;
// 設置與.NET提供的webservice保持較好的兼容性
envelope.dotNet = true;
// 調用webservice
ht.call(SERVICE_NAMESPACE + methodName, envelope);
if (envelope.getResponse() != null) {
// 獲取服務器響應返回的SOAP消息
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName
+ "Result");
// 解析服務器響應的SOAP消息
return parseProvinceOrCity(detail);
}
} catch (SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 根據省份獲取城市列表
public static List<String> getCityListsByProvince(String province) {
// 調用的方法
String methodName = "getSupportCityString";
// 創建httptransportSE傳輸對象
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
ht.debug = true;
// 實例化SoapObject對象
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName);
// 添加一個請求參數
soapObject.addProperty("theRegionCode", province);
// 使用soap1.1協議創建envelop對象
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.bodyOut = soapObject;
// 設置與.NET提供的webservice保持較好的兼容性
envelope.dotNet = true;
// 調用webservice
try {
ht.call(SERVICE_NAMESPACE + methodName, envelope);
if (envelope.getResponse() != null) {
// 獲取服務器響應返回的SOAP消息
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName
+ "Result");
// 解析服務器響應的SOAP消息
return parseProvinceOrCity(detail);
}
} catch (SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// 解析省份或城市
public static List<String> parseProvinceOrCity(SoapObject detail) {
ArrayList<String> result = new ArrayList<>();
for (int i = 0; i < detail.getPropertyCount(); i++) {
// 解析出每個省份
result.add(detail.getProperty(i).toString().split(",")[0]);
}
return result;
}
// 根據城市字符串獲取相應天氣情況
public static SoapObject getWeatherByCity(String cityName) {
String methodName = "getWeather";
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
ht.debug = true;
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName);
soapObject.addProperty("theCityCode", cityName);
soapObject.addProperty("theUserID", "d54a91e159fd40a8b10a0ff9a92944eb");
envelope.bodyOut = soapObject;
envelope.dotNet = true;
try {
ht.call(SERVICE_NAMESPACE + methodName, envelope);
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject detail = (SoapObject) result.getProperty(methodName
+ "Result");
return detail;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
~~~
`
### 2.2.2 主界面布局
`
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="省份:" />
<Spinner
android:id="@+id/sp_province"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="城市:" />
<Spinner
android:id="@+id/sp_city"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:id="@+id/tv_current_weather"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ListView
android:id="@+id/weather_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
~~~
`
### 2.2.3 列表布局
`
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/icon_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/weather"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0" />
</LinearLayout>
~~~
`
### 2.2.4 Activity代碼
`
~~~
package cn.zhaoliang5156.demo;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import org.ksoap2.serialization.SoapObject;
import java.util.ArrayList;
import java.util.List;
/**
* 天氣預報主界面
* @author zhaoliang
* @version 1.0
*/
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int UPDATE_PROVICE = 0x01;
private static final int UPDATE_CITY = 0x02;
private static final int UPDATE_WEATHER = 0x03;
// 聲明對象
private Spinner spProvince, spCity;
private TextView tvCurrentWeather;
private ListView lvWeather;
// 聲明數據集合
private List<String> provinces = new ArrayList<>();
private List<String> citys = new ArrayList<>();
// 頁面數據適配器
private ArrayAdapter<String> provinceAdapter;
private ArrayAdapter<String> cityAdapter;
private SoapObject watherDetail = null;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_PROVICE:
provinceAdapter.notifyDataSetChanged();
break;
case UPDATE_CITY:
cityAdapter.notifyDataSetChanged();
break;
case UPDATE_WEATHER:
lvWeather.setAdapter(new WeatherAdapter(MainActivity.this, watherDetail));
// tvCurrentWeather.setText(watherDetail.getProperty(7).toString());
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindView();
initData();
}
/**
* 初始化 省份和城市
*/
private void initData() {
provinceAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, provinces);
spProvince.setAdapter(provinceAdapter);
cityAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, citys);
spCity.setAdapter(cityAdapter);
getProvince();
getCity("黑龍江");
}
/**
* 綁定視圖
*/
private void bindView() {
spProvince = findViewById(R.id.sp_province);
spCity = findViewById(R.id.sp_city);
tvCurrentWeather = findViewById(R.id.tv_current_weather);
lvWeather = findViewById(R.id.weather_list);
spProvince.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
getCity(provinces.get(position));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spCity.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
getWeather(citys.get(position));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
/**
* 獲取省份
*/
private void getProvince() {
new Thread() {
@Override
public void run() {
provinces.clear();
provinces.addAll(WebServiceUtil.getProvinceList());
mHandler.sendEmptyMessage(UPDATE_PROVICE);
}
}.start();
}
/**
* 獲取城市
*
* @param province
*/
private void getCity(final String province) {
new Thread() {
@Override
public void run() {
citys.clear();
citys.addAll(WebServiceUtil.getCityListsByProvince(province));
mHandler.sendEmptyMessage(UPDATE_CITY);
}
}.start();
}
/**
* 獲取天氣
*
* @param city
*/
private void getWeather(final String city) {
new Thread() {
@Override
public void run() {
watherDetail = null;
watherDetail = WebServiceUtil.getWeatherByCity(city);
mHandler.sendEmptyMessage(UPDATE_WEATHER);
}
}.start();
}
}
~~~
`
### 2.2.5 ListAdapter代碼
`
~~~
package cn.zhaoliang5156.demo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import org.ksoap2.serialization.SoapObject;
/**
* 天氣列表適配器
*
* @author zhaoliang
* @version 1.0
*/
public class WeatherAdapter extends BaseAdapter {
private Context context;
private SoapObject data;
private int iconOne = 10;
private int iconTwo = 11;
private int weatherOne = 7;
private int weatherTwo = 8;
private int weatherThree = 9;
public WeatherAdapter(Context context, SoapObject data) {
this.context = context;
this.data = data;
}
@Override
public int getCount() {
return data == null ? 0 : 5;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHodler hodler = null;
if (convertView == null) {
hodler = new ViewHodler();
convertView = LayoutInflater.from(context).inflate(R.layout.list_item, null);
hodler.ivIconOne = convertView.findViewById(R.id.icon_one);
hodler.ivIconTwo = convertView.findViewById(R.id.icon_two);
hodler.tvWeather = convertView.findViewById(R.id.weather);
convertView.setTag(hodler);
} else {
hodler = (ViewHodler) convertView.getTag();
}
hodler.ivIconOne.setImageResource(parseIcon(data.getProperty(iconOne).toString()));
hodler.ivIconTwo.setImageResource(parseIcon(data.getProperty(iconTwo).toString()));
hodler.tvWeather.setText(data.getProperty(weatherOne) + "\n" + data.getProperty(weatherTwo) + "\n" + data.getProperty(weatherThree));
iconOne += 5;
iconTwo += 5;
weatherOne += 5;
weatherTwo += 5;
weatherThree += 5;
return convertView;
}
class ViewHodler {
ImageView ivIconOne;
ImageView ivIconTwo;
TextView tvWeather;
}
// 工具方法,該方法負責把返回的天氣圖標字符串,轉換為程序的圖片資源ID。
private int parseIcon(String strIcon) {
if (strIcon == null)
return -1;
if ("0.gif".equals(strIcon))
return R.drawable.a_0;
if ("1.gif".equals(strIcon))
return R.drawable.a_1;
if ("2.gif".equals(strIcon))
return R.drawable.a_2;
if ("3.gif".equals(strIcon))
return R.drawable.a_3;
if ("4.gif".equals(strIcon))
return R.drawable.a_4;
if ("5.gif".equals(strIcon))
return R.drawable.a_5;
if ("6.gif".equals(strIcon))
return R.drawable.a_6;
if ("7.gif".equals(strIcon))
return R.drawable.a_7;
if ("8.gif".equals(strIcon))
return R.drawable.a_8;
if ("9.gif".equals(strIcon))
return R.drawable.a_9;
if ("10.gif".equals(strIcon))
return R.drawable.a_10;
if ("11.gif".equals(strIcon))
return R.drawable.a_11;
if ("12.gif".equals(strIcon))
return R.drawable.a_12;
if ("13.gif".equals(strIcon))
return R.drawable.a_13;
if ("14.gif".equals(strIcon))
return R.drawable.a_14;
if ("15.gif".equals(strIcon))
return R.drawable.a_15;
if ("16.gif".equals(strIcon))
return R.drawable.a_16;
if ("17.gif".equals(strIcon))
return R.drawable.a_17;
if ("18.gif".equals(strIcon))
return R.drawable.a_18;
if ("19.gif".equals(strIcon))
return R.drawable.a_19;
if ("20.gif".equals(strIcon))
return R.drawable.a_20;
if ("21.gif".equals(strIcon))
return R.drawable.a_21;
if ("22.gif".equals(strIcon))
return R.drawable.a_22;
if ("23.gif".equals(strIcon))
return R.drawable.a_23;
if ("24.gif".equals(strIcon))
return R.drawable.a_24;
if ("25.gif".equals(strIcon))
return R.drawable.a_25;
if ("26.gif".equals(strIcon))
return R.drawable.a_26;
if ("27.gif".equals(strIcon))
return R.drawable.a_27;
if ("28.gif".equals(strIcon))
return R.drawable.a_28;
if ("29.gif".equals(strIcon))
return R.drawable.a_29;
if ("30.gif".equals(strIcon))
return R.drawable.a_30;
if ("31.gif".equals(strIcon))
return R.drawable.a_31;
return 0;
}
}
~~~
`
- 咨詢項目實戰
- 第一單元 HTTP協議
- 1.1 OSI七層模型
- 1.2 HTTP協議(重點)
- 1.3 HTTPS協議(了解)
- 1.4 TCP/IP協議擴展
- 1.5 WebService簡介及實戰(無接口)
- 1.6 課后練習
- 第二單元 HTTPURLConnection
- 2.1 ANR
- 2.2 網絡判斷
- 2.3 HTTPURLConnection
- 2.4 課后練習
- 第三單元 AsyncTask
- 3.1 AsyncTask概述
- 3.2 AsyncTask基本使用
- 3.3 課后練習
- 第四單元 圖片異步加載
- 4.1 圖片異步加載概述
- 4.2 LruCache
- 4.3 DiskLRUCache
- 4.4 圖片三級緩存概述
- 4.5 封裝圖片加載緩存框架
- 第五單元 ListView多條目
- 5.1 ListView多條目概述
- 5.2 ListView多條目的使用
- 第六單元 ListView實現下拉刷新上拉加載
- 6.1 下拉刷新和上拉加載更多
- 6.2 XListView概述
- 6.3 XListView的使用
- 第七單元 封裝網絡框
- 7.1 封裝網絡框架概述
- 7.2 網絡框架的封裝
- 第八單元 項目介紹
- 8.1 公司項目團隊架構簡介
- 8.2 項目文檔及項目流程介紹
- 8.3 項目管理
- 8.4 項目開發
- 第九單元 項目框架搭建
- 9.1 基類封裝概述
- 9.2 Application中初始化配置
- 9.3 項目中的工具類
- 9.4 封裝網絡請求框架
- 9.5 封裝圖片異步緩存框架
- 第十單元 搭建UI框架1
- 10.1 側滑菜單概述
- 10.2 主界面框架搭建
- 第十一單元 搭建UI框架2
- 11.1 TabLayout的概述
- 11.2 TabLayout的使用
- 第十二單元 圖片上傳
- 12.1 圖片上傳概述
- 12.2 圖片上傳的實現
- 第十三單元 PullToRefresh
- 13.1 PullToRefresh概述
- 13.2 PullToRefresh的使用
- 13.3 緩存業務實現思路
- 第十四單元 事件分發及滑動沖突
- 14.1 事件分發概述
- 14.2 事件分發流程
- 14.3 事件分發的使用
- 第十五單元 傳感器的基本使用
- 15.1 傳感器概述
- 15.2 傳感器的使用
- 第十六單元 HTML與CSS復習
- 16.1 HTML
- 16.2 CSS
- 第十七單元 js復習
- 17.1 js基礎語法
- 17.2 js數組和內置對象
- 17.3 js常用事件
- 17.4 js對象模型
- 17.5 js 正則表達式
- 第十八單元 WebView
- 18.1 WebView 概述
- 18.2 WebView的使用
- 18.3 WebView與js交互
- 第十九單元 項目案例
- 項目概述
- 第二十單元 項目答辯
- 周考
- 第一周周考
- 第二周周考
- 第三種周考
- 月考
- 接口文檔