您的位置:首页 > 移动开发 > Android开发

Android调用WebService(图文教程)

2013-07-08 17:32 337 查看

WebService服务端的建立

创建一个WebService项目

在myeclipse中进行 File-->new-->Web Service Project进入如下界面填写工程名之后直接完成即可。



接着建立需要的各种类。跟常规建类的方法没有区别

项目名称-->src目录下右击-->new-->Class

我这里建立两个类一个是主要的操作类,一个是模拟的entity类

主类操作类

Test.java

package com.demo.test;

import java.util.ArrayList;
import java.util.List;

import com.demo.test.entity.UserInfo;

public class Test {

public String getNumString() {
return "12300000000";
}

/**
* 获取用户信息
* @return
*/
public List<UserInfo> getUser() {
List<UserInfo> list = new ArrayList<UserInfo>();
UserInfo userInfo = new UserInfo();

userInfo.setId(1);
userInfo.setUserName("张三");
userInfo.setPassword("123");
userInfo.setSex("男");
userInfo.setAge(19);
list.add(userInfo);

userInfo = new UserInfo();
userInfo.setId(2);
userInfo.setUserName("李四");
userInfo.setPassword("456");
userInfo.setSex("女");
userInfo.setAge(18);
list.add(userInfo);

return list;
}

/**
* 根据ID获取用户信息
* @return
*/
public UserInfo getUserById(int id) {
UserInfo userInfo = new UserInfo();

userInfo.setId(id);
userInfo.setUserName("虚拟用户:张三");
userInfo.setPassword("123");
userInfo.setSex("男");
userInfo.setAge(19);

return userInfo;
}

}


其中定义了三个方法,是为了进行测试用的,首先第一种方法是单纯的返回一个字符串,第二个方法是返回一个List,第三个方法是经过传入参数来查找用户。

上面用到的entity如下

UserInfo.java

package com.demo.test.entity;

public class UserInfo {

private int id = 0;
private String userName = null;
private String password = null;
private int age = 18;
private String sex = null;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

}


接下来的操作才是重点

首先建立webservice服务



接着选择new Web Service进入如下界面 并且在strategy中选择第二个(根据java文件创立webservice)



接着进行下一步

在java class中选择已经写好的test.java类 并且选中Generate wsdl in project.最后点击finish



到这一步webservice已经开发的差不多了。最后一步 需要添加jar包

右击项目名-->build path-->Configure Build Path...-->Add Library-->Myeclipse Libraries-->然后选择关于JAX-WS的两个包



详细配置如下:







在此需要说明一点TestDelegate.java类是自动生成的,其中记录了很多重要的信息。

如Namespace、URL、portName等等

package com.demo.test;

import java.util.ArrayList;
import java.util.List;
import com.demo.test.entity.UserInfo;

@javax.jws.WebService(targetNamespace = "http://test.demo.com/", serviceName = "TestService", portName = "TestPort", wsdlLocation = "WEB-INF/wsdl/TestService.wsdl")
public class TestDelegate {

com.demo.test.Test test = new com.demo.test.Test();

public String getNumString() {
return test.getNumString();
}

public List<UserInfo> getUser() {
return test.getUser();
}

public UserInfo getUserById(int id) {
return test.getUserById(id);
}

}


至此,webService已经开发完毕了 接着将项目部署到tomcat中,然后开启tomcat 接着访问

http://localhost:8080/WebServicePro/TestPort?wsdl

如果看到以下界面说明已经WebService已经开发完成了。



接着下来是开发Android端

在Android开发的时候这里需要使用一个jar包

下载该夹包可以直接登录http://code.google.com/p/ksoap2-android/,现在该站点已经提供了直接的下载,只要点击下载链接就可以下载了;

百度网盘地址:点击打开链接(ksoap2-android-assembly-3.0.0-jar-with-dependencies.jar)

android中通过webservice调用服务器端其实还是很简单的,只要按部就班的按照下面步骤进行即可:

(1)创建HttpTransportSE对象,该对象用于调用WebService操作

HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);


(2)创建SoapSerializationEnvelope对象

// 使用soap1.1协议创建Envelop对象
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);


(3)创建SoapObject对象,创建该对象时需要传入所要调用的Web Service的命名空间和WebService方法名

// 实例化SoapObject对象
SoapObject object = new SoapObject(SERVICE_NAMESPACE, mathodName);


(4)如果有参数传给Web Service服务器端,调用SoapObject对象的addProperty(String name, Object value)方法来设置参数,该方法的name参数指定参数名

  注意:参数名不一定要与服务端的方法中的参数名相同,只要对应顺序相同即可;value参数指定参数值

// 设置参数
object.addProperty("id", 1);

(5)调用SoapSerializationEnvelope的setOutputSoapObject()方法,或者直接对bodyOut属性赋值,将前两步创建的SoapObject对象设为SoapSerializationEnvelope

  的传出SOAP消息体

// 将SoapObject对象设置为SoapSerializationEnvelope对象的传出SOAP消息
envelope.bodyOut = object;


(6)调用对象的call()方法,并以SoapSerializationEnvelope作为参数调用远程的web service

// 调用webService
ht.call(null, envelope);


(7)掉用完成后,访问SoapSerializationEnvelope对象的bodyIn属性,该属性返回一个SoapObject对象,该对象就代表Web service的返回消息,解析该对象,即可获得

  调用web service的返回值

SoapObject result = (SoapObject) envelope.bodyIn;
String name = result.getProperty(0).toString();


以上步骤参照/article/4765626.html 可以去看看

下来为代码实例

activity_main.xml

<ScrollView 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >

<TextView
android:id="@+id/hello"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />

<EditText
android:id="@+id/edit1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/hello"
android:inputType="textMultiLine" />

<EditText
android:id="@+id/edit2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/edit1"
android:inputType="textMultiLine" />

<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/edit2"
android:layout_below="@+id/edit2"
android:text="无参数查询" />

<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/button1"
android:layout_alignBottom="@+id/button1"
android:layout_alignRight="@+id/edit2"
android:text="有参数查询" />
</RelativeLayout>

</ScrollView>


此代码中定义了调用了WebService服务端的三个代码

1、当用户刚开始进入的时候默认调用返回字符串的方法getNumString(0

2、当用户点击无参数查询的时候调用List<UserInfo> getUser() 方法返回一个List

3、当用户点击有参数查询的时候调用UserInfo getUserById(int id) 方法,传参查找具体内容

MainActivity.java

package com.demo.webserviceclient;

import java.io.IOException;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

@SuppressLint("NewApi")
public class MainActivity extends Activity {

// 在webService服务端中可以找到NAMESPAC的具体内容
private static final String SERVICE_NAMESPACE = "http://test.demo.com/";
// URL
private static final String SERVICE_URL = "http://192.168.1.104:8080/WebServicePro/TestPort?wsdl";

private EditText edit1 = null;
private EditText edit2 = null;

private Button btn1 = null;
private Button btn2 = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

edit1 = (EditText) findViewById(R.id.edit1);
edit2 = (EditText) findViewById(R.id.edit2);
btn1 = (Button) findViewById(R.id.button1);
btn2 = (Button) findViewById(R.id.button2);

// 如果本系统为4.0以上(Build.VERSION_CODES.ICE_CREAM_SANDWICH为android4.0)
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
// 详见StrictMode文档
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads().detectDiskWrites().detectNetwork()
.penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects().detectLeakedClosableObjects()
.penaltyLog().penaltyDeath().build());
}

// 调用的方法
String mathodName = "getNumString";
// 创建HttpTransportSE对象
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
ht.debug = true;

// 使用soap1.1协议创建Envelop对象
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);

// 实例化SoapObject对象
SoapObject object = new SoapObject(SERVICE_NAMESPACE, mathodName);

// 将SoapObject对象设置为SoapSerializationEnvelope对象的传出SOAP消息
envelope.bodyOut = object;

try {
// 调用webService
ht.call(null, envelope);
System.out.println("envelope.getResponse()---"
+ envelope.getResponse());
if (envelope.getResponse() != null) {
SoapObject result = (SoapObject) envelope.bodyIn;
String name = result.getProperty(0).toString();
edit1.setText("返回值为:" + name);

} else {
edit1.setText("无返回值");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

btn1.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {

// 调用的方法
String mathodName = "getUser";
// 创建HttpTransportSE对象
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
ht.debug = true;

// 使用soap1.1协议创建Envelop对象
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);

// 实例化SoapObject对象
SoapObject object = new SoapObject(SERVICE_NAMESPACE, mathodName);

// 将SoapObject对象设置为SoapSerializationEnvelope对象的传出SOAP消息
envelope.bodyOut = object;

try {
// 调用webService
ht.call(null, envelope);
edit2.setText("回传的值 :"+envelope.getResponse());
if (envelope.getResponse() != null) {
SoapObject result = (SoapObject) envelope.bodyIn;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < result.getPropertyCount(); i++) {
SoapObject msg = (SoapObject) result.getProperty(i);
if (msg != null) {
sb.append("名称[").append(i).append("]\t\t").append(msg.getProperty(4).toString()).append("\n");
sb.append("年龄[").append(i).append("]\t\t").append(msg.getProperty(0).toString()).append("\n");
sb.append("ID[").append(i).append("]\t\t").append(msg.getProperty(1).toString()).append("\n");
sb.append("密码[").append(i).append("]\t\t").append(msg.getProperty(2).toString()).append("\n");
sb.append("性别[").append(i).append("]\t\t").append(msg.getProperty(3).toString()).append("\n").append("\n");
}

}
edit1.setText(sb);
} else {
edit1.setText("无返回");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
});

btn2.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {

// 调用的方法
String mathodName = "getUserById";
// 创建HttpTransportSE对象
HttpTransportSE ht = new HttpTransportSE(SERVICE_URL);
ht.debug = true;

// 使用soap1.1协议创建Envelop对象
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);

// 实例化SoapObject对象
SoapObject object = new SoapObject(SERVICE_NAMESPACE, mathodName);

// 设置参数
object.addProperty("id", 1);

// 将SoapObject对象设置为SoapSerializationEnvelope对象的传出SOAP消息
envelope.bodyOut = object;

try {
// 调用webService
ht.call(null, envelope);
edit2.setText("回传的值 :"+envelope.getResponse());
if (envelope.getResponse() != null) {
SoapObject result = (SoapObject) envelope.bodyIn;
SoapObject msg = (SoapObject) result.getProperty(0);
StringBuilder sb = new StringBuilder();
sb.append("名称\t\t").append(msg.getProperty(4).toString()).append("\n");
sb.append("年龄\t\t").append(msg.getProperty(0).toString()).append("\n");
sb.append("I   D\t\t").append(msg.getProperty(1).toString()).append("\n");
sb.append("密码\t\t").append(msg.getProperty(2).toString()).append("\n");
sb.append("性别\t\t").append(msg.getProperty(3).toString()).append("\n").append("\n");

edit1.setText(sb);
} else {
edit1.setText("无返回");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
});

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}


最后在AndroidManifest.xml中加入访问网络权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.demo.webserviceclient"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.demo.webserviceclient.MainActivity"
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>


运行结果如下:初始界面



当点击无参数查询的时候运行结果如下(因为使用了ScrollView,因此可以上下滚动)



当点击了有参数查询的时候



PS:getPropert的使用次数至关重要,这里主要看返回值的层次,没有掌握的时候可以debug调试跟跟代码进行增加减。

如果不对会产生java.lang.ClassCastException: org.ksoap2.serialization.SoapPrimitive cannot的错误提示。进入debug中调试调试就ok了。

PPS:以上的代码其实还是不健全的,会发现调用service中方法时传参为null

因为细心的话就可以发现,在有参数查询的时候参数的值并没有传过去,其实就是这句代码

// 设置参数
object.addProperty("id", 1);
当将参数名与服务器端保持一致,但不成功

但是当这里的参数设置为arg0、arg1、arg2……argn的时候竟然是正确的。

正确代码如下:

// 设置参数

object.addProperty("arg0", 1);

截图在这里就不截了,内容就是上面图中的id=0显示为id=1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: