一、获取并使用KSOAP包
在Android SDK中并没有提供调用WebService的库,因此,需要使用第三方的SDK来调用WebService。PC版本的WebService库非常丰富,但这些对Android来说过于庞大。适合手机的WebService客户端的SDK有一些,比较常用的是KSOAP2。
KSOAP2 地址:http://code.google.com/p/ksoap2-android/
二、添加SOAP到Android工程
下载后得到SOAP压缩包将压缩包解压将JAR类型文件添加的到安卓工程具体步骤如下图:
步骤一、
选择我们的项目,右键菜单中 Build Path –> Add External Archives… 增加这个下载的JAR包
增加好后,我们在 选择我们的项目,右键菜单中 Build Path –> Configure Build Path 的 Libraries 中可以看到下面图我们下载的到的
ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar已经被导入安卓工程。
步骤二、切换到Order and Export 的tab ,选择在ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar前的checkBox点击OK。切记不要选择Android4.x安卓自带的库否则运行也会执行出错,如图我没有选择Android 4,.3(具体原因目前尚未搞懂)
说完了整个环境的搭建,我们在来说说WebService 调用的步骤:
1、指定 WebService 的命名空间和调用方法
import org.ksoap2.serialization.SoapObject;
private static final String NAMESPACE = "http://WebXml.com.cn/";
private static final String METHOD_NAME = "getWeatherbyCityName";
SoapObject rpc = new SoapObject(NAMESPACE, METHOD_NAME);
SoapObject类的第一个参数表示WebService的命名空间,可以从WSDL文档中找到WebService的命名空间
第二个参数表示要调用的WebService方法名。
2、设置调用方法的参数值,如果没有参数,可以省略,设置方法的参数值的代码如下:
rpc.addProperty("theCityName", "广州");
3、生成调用Webservice方法的SOAP请求信息。
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.setOutputSoapObject(rpc);
创建SoapSerializationEnvelope对象时需要通过SoapSerializationEnvelope类的构造方法设置SOAP协议的版本号。
该版本号需要根据服务端WebService的版本号设置。
在创建SoapSerializationEnvelope对象后,不要忘了设置SOAPSoapSerializationEnvelope类的bodyOut属性,
该属性的值就是在第一步创建的SoapObject对象。
4、创建HttpTransportsSE对象。
这里不要使用 AndroidHttpTransport ht = new AndroidHttpTransport(URL); 这是一个要过期的类
private static String URL = "http://www.webxml.com.cn/webservices/weatherwebservice.asmx";
HttpTransportSE ht = new HttpTransportSE(URL);
ht.debug = true;
5、使用call方法调用WebService方法
private static String SOAP_ACTION = "http://WebXml.com.cn/getWeatherbyCityName";
ht.call(SOAP_ACTION, envelope);
第一个参数可以为null,第2个参数就是在第3步创建的SoapSerializationEnvelope对象。
6、获得WebService方法的返回结果
有两种方法:
1、使用getResponse方法获得返回数据。
private SoapObject detail;
detail =(SoapObject) envelope.getResponse();
2、使用 bodyIn 及 getProperty。
private SoapObject detail;
SoapObject result = (SoapObject)envelope.bodyIn;
detail = (SoapObject) result.getProperty("getWeatherbyCityNameResult");
7、访问webService的主要代码要写在子线程中在安卓4.0平台不允许直接在UI线程也就是Activity的主线程简历网络连接、访问网络资源,因为这些访问通常是阻塞操作会影响到UI的流畅性这也是安卓4.0平台以后的一个优化,因此为了防止出现一些bug我们最好在子线程中进行webService访问,通过handler将子线程消息返回到主线程中。
8、这时候不要忘记在改 AndroidManifest.xml 文件,添加网络访问权限
9、这时候你辛辛苦苦写好所有主程序的时候,不断地进行调试,不断地发现Source Not Found这样的异常程序崩溃,你往往会异常郁闷和纠结怀疑是不是自己写的程序不对,怀疑哪里出现了空引用,是不是环境没有搭建好,其实可能不是,
只是没人提醒你在AndroidManifest.xml中要移除对sdk版本的限制,也下面的xml代码:
<uses-sdk android:minSdkVersion="10"
android:targetSdkVersion="18" />
完整的 AndroidManifest.xml 文件如下:
完整的Java代码如下:
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import org.ksoap2.*;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;
import android.widget.*;
public class WeatherActivity extends Activity {
private static final String NAMESPACE = "http://WebXml.com.cn/";
private static String URL = "http://www.webxml.com.cn/webservices/weatherwebservice.asmx";
private static final String METHOD_NAME = "getWeatherbyCityName";
private static String SOAP_ACTION = "http://WebXml.com.cn/getWeatherbyCityName";
private String weatherToday;
private SoapObject detail;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_weather);
Button button = (Button)findViewById(R.id.button1);
final Handler handler = new Handler()
{
public void handleMessage(Message msg)
{
if(msg.what==0x123)
Toast.makeText(WeatherActivity.this, msg.obj.toString(), Toast.LENGTH_LONG).show();
}
};
button.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
String city = "广州";
SoapObject rpc = new SoapObject(NAMESPACE,METHOD_NAME);
rpc.addProperty("theCityName", city);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = rpc;
envelope.dotNet = true;
envelope.setOutputSoapObject(rpc);
HttpTransportSE ht = new HttpTransportSE(URL);
getWeatherThread thread =new getWeatherThread(handler,ht,envelope);
new Thread(thread).start();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.weather, menu);
return true;
}
class getWeatherThread implements Runnable
{
private HttpTransportSE ht;
private Handler handler;
SoapSerializationEnvelope envelope;
public getWeatherThread(Handler handler,HttpTransportSE ht,SoapSerializationEnvelope envelope)
{
this.handler = handler;
this.ht = ht;
this.envelope = envelope;
}
@Override
public void run() {
ht.debug = true;
try {
ht.call(SOAP_ACTION, envelope);
detail =(SoapObject) envelope.getResponse();
System.out.println("detail" + detail);
String weather = parseWeather(detail);
Message msg = new Message();
msg.obj = weather;
msg.what =0x123;
handler.sendMessage(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private String parseWeather(SoapObject detail)
throws UnsupportedEncodingException {
String date = detail.getProperty(6).toString();
weatherToday = "今天:" + date.split(" ")[0];
weatherToday = weatherToday + "\n天气:" + date.split(" ")[1];
weatherToday = weatherToday + "\n气温:"
+ detail.getProperty(5).toString();
weatherToday = weatherToday + "\n风力:"
+ detail.getProperty(7).toString() + "\n";
return weatherToday;
}
}
}
Layout.xml省略
本文所参考资料:
Android调用天气预报的WebService简单例子
http://www.cnblogs.com/ghj1976/archive/2011/04/26/2028904.html
红色字体部分是本人在实验过程中遇到的问题,希望大家可以吸取教训。
本人水平有限希望同行高手发现错误不吝赐教,尚未解决的问题可以回答一二谢谢。