Android WebService简单教程与Source Not found异常解决方案

一、获取并使用KSOAP包

在Android SDK中并没有提供调用WebService的库,因此,需要使用第三方的SDK来调用WebService。PC版本的WebService库非常丰富,但这些对Android来说过于庞大。适合手机的WebService客户端的SDK有一些,比较常用的是KSOAP2。

KSOAP2 地址:http://code.google.com/p/ksoap2-android/


二、添加SOAP到Android工程

下载后得到SOAP压缩包将压缩包解压将JAR类型文件添加的到安卓工程具体步骤如下图:

Android WebService简单教程与Source Not found异常解决方案_第1张图片

步骤一、

选择我们的项目,右键菜单中 Build Path –> Add External Archives… 增加这个下载的JAR包

Android WebService简单教程与Source Not found异常解决方案_第2张图片

增加好后,我们在 选择我们的项目,右键菜单中 Build Path –> Configure Build Path 的 Libraries 中可以看到下面图我们下载的到的

ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar已经被导入安卓工程。

Android WebService简单教程与Source Not found异常解决方案_第3张图片



步骤二、切换到Order and Export 的tab ,选择在ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar前的checkBox点击OK。切记不要选择Android4.x安卓自带的库否则运行也会执行出错,如图我没有选择Android 4,.3(具体原因目前尚未搞懂)

Android WebService简单教程与Source Not found异常解决方案_第4张图片

说完了整个环境的搭建,我们在来说说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_ACTIONenvelope);

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

 

红色字体部分是本人在实验过程中遇到的问题,希望大家可以吸取教训。

本人水平有限希望同行高手发现错误不吝赐教,尚未解决的问题可以回答一二谢谢。







你可能感兴趣的:(Android学习笔记)