google為ndroid平臺開發web service提供了支持,提供了ksoap2-android相關架包
1.下載該夾包可以直接登錄http://code.google.com/p/ksoap2-android/,現在該站點已經提供了直接的下載,只要點擊下載鏈接就可以下載了;
我現在的是ksoap2-android-assembly-2.6.5-jar-with-dependencies.jar
2.好了,現在我們就可以進行新建項目來進行測試了,首先我們先建立java服務端,這里的一些前期準備我就不說了(比如與spring的整合等示例),
由于這里重點是android客戶端,java服務器端就直接給代碼了
interface:(這里提供了兩個方法,一個傳遞的是簡單字符串,另一個傳遞的是符合對象+集合)
復制代碼 代碼如下:
package xidian.sl.service.webservice;
import javax.jws.webparam;
import javax.jws.webservice;
import javax.jws.soap.soapbinding;
import javax.jws.soap.soapbinding.style;
import xidian.sl.service.impl.webservice.studentlist;
@webservice
@soapbinding(style = style.rpc)
public interface testservice {
public string getuser(@webparam(name = "name")string name);
public studentlist getstulist();
}
implement:
復制代碼 代碼如下:
package xidian.sl.service.impl.webservice;
import java.util.arraylist;
import java.util.list;
import javax.jws.webservice;
import xidian.sl.entity.students;
import xidian.sl.service.webservice.testservice;
@webservice(endpointinterface = "xidian.sl.service.webservice.testservice")
public class testserviceimpl implements testservice {
@override
public string getuser(string name) {
system.out.println("客戶端傳遞的名字為 = "+name);
return name;
}
@override
public studentlist getstulist() {
system.out.println("該方法被調用");
list<students> stulist = new arraylist<students>();
//第一個學生
students stu1 = new students();
stu1.setstuname("沈浪");
stu1.setstunum("1006010054");
stu1.setstusex("男");
stulist.add(stu1);
//第二個學生
students stu2 = new students();
stu2.setstuname("香香");
stu2.setstunum("1006010043");
stu2.setstusex("女");
stulist.add(stu2);
//將list集合封裝成一個對象才能在webservice中進行傳遞
studentlist studentlist = new studentlist();
studentlist.setstulist(stulist);
return studentlist;
}
}
list的封裝對象
復制代碼 代碼如下:
package xidian.sl.service.impl.webservice;
import java.util.list;
import xidian.sl.entity.students;
public class studentlist {
private list<students> stulist;
public list<students> getstulist() {
return stulist;
}
public void setstulist(list<students> stulist) {
this.stulist = stulist;
}
}
然后在srping的整合配置文件中進行如下配置即可(默認web.xml中已經進行配置)
復制代碼 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemalocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:meta-inf/cxf/cxf.xml" /> <!-- 這些xml文件在cxf-2.5.0.jar的meta-inf目錄下-->
<!--<import resource="classpath:meta-inf/cxf/cxf-extension-soap.xml" />
警告提示已經廢棄了cxf-extension-soap.xml文件-->
<import resource="classpath:meta-inf/cxf/cxf-servlet.xml" />
<!-- 這里配置服務接口,后面描述
id:指在spring配置的bean的id.
implementor:指明具體的實現類.
address:指明這個web service的相對地址
-->
<!-- 測試 -->
<bean id="testserviceimpl" class="xidian.sl.service.impl.webservice.testserviceimpl" >
</bean>
<jaxws:endpoint id="testservice"
implementor="#testserviceimpl"
address="/test" />
<!-- 開啟tomcat服務器 ,訪問http://localhost:8080/webexam/services/test?wsdl
http://localhost:8080/webexam是本項目的訪問地址
services是由于web.xml配置所得,test是由于spring配置文件中的address屬性所得
-->
</beans>
3.到此服務器端的已經建立完全,我們可以測試下:開啟tomcat,然后在瀏覽器中輸入http://localhost:8090/webexam/services/test?wsdl可以查看wsdl
現在我們就可以開始建立android客戶端了
新建一個項目后導入ksoap2-android-assembly-2.6.5-jar-with-dependencies.jar,這里要特別注意:導入包的方式不要選擇項目右鍵---->build path---->
add external archives...,如果使用這種方式表面上好像是導入了包,但還是沒有辦法引用到,然后啟動項目后一直會報:
我們還是選擇和開發web一樣的方式,就是在項目下新建lib或者libs文件夾,然后將jar直接復制到該文件夾中,ide會幫助直接引入的:
這樣就正確無誤了,不再會報類無法引用到了
android中通過webservice調用服務器端其實還是很簡單的,只要按部就班的按照下面步驟進行即可:
(1)創建httptransportse對象,該對象用于調用webservice操作
復制代碼 代碼如下:
httptransportse ht = new httptransportse(service_url);
(2)創建soapserializationenvelope對象
復制代碼 代碼如下:
soapserializationenvelope envelope = new soapserializationenvelope
(soapenvelope.ver11);
(3)創建soapobject對象,創建該對象時需要傳入所要調用的web service的命名空間和webservice方法名
復制代碼 代碼如下:
soapobject request = new soapobject(service_ns, methodname);
(4)如果有參數傳給web service服務器端,調用soapobject對象的addproperty(string name, object value)方法來設置參數,該方法的name參數指定參數名
注意:參數名不一定要與服務端的方法中的參數名相同,只要對應順序相同即可;value參數指定參數值
復制代碼 代碼如下:
request.addproperty("name", "1006010054");
(5)調用soapserializationenvelope的setoutputsoapobject()方法,或者直接對bodyout屬性賦值,將前兩步創建的soapobject對象設為soapserializationenvelope的傳出soap消息體
復制代碼 代碼如下:
envelope.bodyout = request;
(6)調用對象的call()方法,并以soapserializationenvelope作為參數調用遠程的web service
復制代碼 代碼如下:
ht.call(null, envelope);
(7)掉用完成后,訪問soapserializationenvelope對象的bodyin屬性,該屬性返回一個soapobject對象,該對象就代表web service的返回消息,解析該對象,即可獲得調用web service的返回值
復制代碼 代碼如下:
soapobject result = (soapobject) envelope.bodyin;
string name = result.getproperty(0).tostring();
下面給書具體的實例:
mian.xml很簡單就是兩個編輯框:
復制代碼 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<textview
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<edittext
android:id="@+id/edittext1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" >
<requestfocus />
</edittext>
<edittext
android:id="@+id/edittext2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10" />
</linearlayout>
activity:(該activity調用了服務器端返回普通字符串的方法)
復制代碼 代碼如下:
package xidian.sl.android.webservice;
import org.ksoap2.soapenvelope;
import org.ksoap2.serialization.soapobject;
import org.ksoap2.serialization.soapserializationenvelope;
import org.ksoap2.transport.httptransportse;
import android.app.activity;
import android.os.bundle;
import android.widget.edittext;
public class webservicesimpledemo extends activity{
final static string service_ns = "http://webservice.service.sl.xidian/";
final static string service_url = "http://192.168.1.103:8090/webexam/services/test";
private edittext txt1;
private edittext txt2;
/** called when the activity is first created. */
@override
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.main);
txt1 = (edittext) findviewbyid(r.id.edittext1);
txt2 = (edittext) findviewbyid(r.id.edittext2);
//調用的方法
string methodname = "getuser";
//創建httptransportse傳輸對象
httptransportse ht = new httptransportse(service_url);
ht.debug = true;
//使用soap1.1協議創建envelop對象
soapserializationenvelope envelope = new soapserializationenvelope(soapenvelope.ver11);
//實例化soapobject對象
soapobject request = new soapobject(service_ns, methodname);
/**
* 設置參數,參數名不一定需要跟調用的服務器端的參數名相同,只需要對應的順序相同即可
* */
request.addproperty("name", "1006010054");
//將soapobject對象設置為soapserializationenvelope對象的傳出soap消息
envelope.bodyout = request;
try{
//調用webservice
ht.call(null, envelope);
//txt1.settext("看看"+envelope.getresponse());
if(envelope.getresponse() != null){
txt2.settext("有返回");
soapobject result = (soapobject) envelope.bodyin;
string name = result.getproperty(0).tostring();
txt1.settext("返回值 = "+name);
}else{
txt2.settext("無返回");
}
}catch (exception e) {
e.printstacktrace();
}
}
}
在androidmanifest.xml進行activity的注冊和并添加訪問網絡的權限
復制代碼 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xidian.sl.android.webservice"
android:versioncode="1"
android:versionname="1.0" >
<uses-sdk android:minsdkversion="10" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".webservicesimpledemo"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.main" />
<category android:name="android.intent.category.launcher" />
</intent-filter>
</activity>
</application>
<!-- 聲明該應用自身所擁有的權限 -->
<uses-permission android:name="android.permission.internet" />
</manifest>
運行后的結果如圖所示:
下面我們來試著調用回傳符合對象的方法:
activity:
復制代碼 代碼如下:
package xidian.sl.android.webservice;
import org.ksoap2.soapenvelope;
import org.ksoap2.serialization.soapobject;
import org.ksoap2.serialization.soapserializationenvelope;
import org.ksoap2.transport.httptransportse;
import android.app.activity;
import android.os.bundle;
import android.widget.edittext;
public class webservicecomplexdemo extends activity{
final static string service_ns = "http://webservice.service.sl.xidian/";
final static string service_url = "http://192.168.1.103:8090/webexam/services/test";
private edittext txt1;
private edittext txt2;
/** called when the activity is first created. */
@override
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.main);
txt1 = (edittext) findviewbyid(r.id.edittext1);
txt2 = (edittext) findviewbyid(r.id.edittext2);
//調用的方法
string methodname = "getstulist";
//創建httptransportse傳輸對象
httptransportse ht = new httptransportse(service_url);
ht.debug = true;
//使用soap1.1協議創建envelop對象
soapserializationenvelope envelope = new soapserializationenvelope(soapenvelope.ver11);
//實例化soapobject對象
soapobject request = new soapobject(service_ns, methodname);
/**
* 設置參數,參數名不一定需要跟調用的服務器端的參數名相同,只需要對應的順序相同即可
* */
//request.addproperty("name", "1006010054");
//將soapobject對象設置為soapserializationenvelope對象的傳出soap消息
envelope.bodyout = request;
try{
//調用webservice
ht.call(null, envelope);
txt2.settext("回傳的值 :"+envelope.getresponse());
if(envelope.getresponse() != null){
soapobject result = (soapobject) envelope.bodyin;
soapobject soapchilds = (soapobject)result.getproperty(0);
stringbuffer sb = new stringbuffer();
for(int i=0; i <soapchilds.getpropertycount(); i++){
soapobject soapchildschilds = (soapobject)soapchilds.getproperty(i);
sb.append("姓名["+i+"] = "+soapchildschilds.getproperty(0).tostring()+"\n");
sb.append("學號["+i+"] = "+soapchildschilds.getproperty(1).tostring()+"\n");
sb.append("性別["+i+"] = "+soapchildschilds.getproperty(2).tostring()+"\n"+"\n");
}
txt1.settext(sb.tostring());
}else{
txt1.settext("無返回");
}
}catch (exception e) {
e.printstacktrace();
}
}
}
區別就是對于返回值的處理上,使用幾次getpropert()方法,這里主要看返回值的層次,看下面的結果應該就能明白了,根據括號的層次來進行確定