首页 > 代码库 > Android使用ksoap2-android调用WebService

Android使用ksoap2-android调用WebService

现在的移动设备根本不可能离得开网络连接,数据的交换。最近学习的是在android端如何去调用远程WebService,都说WebService是一种基于SOAP协议的远程调用标准,对于这个协议理解不深,知道webservice可以将不同操作系统平台、不同语言、不同技术整合到一块,android SDK没有直接调用webservice的库,最常用的是借助ksoap2-android这个第三方SDK,点击打开链接,然后和其他第三方jar包一样导入android项目中即可。

 

1,定义webservice的NAMESPACE和URL

<string name="nameSpace">http://tempuri.org/</string><string name="serviceURL_203">http://public.ebanji.cn/web5/Server/iSchoolServer.asmx</string>

 

2,创建HttpTransportSE传输对象:HttpTransportSE ht = new HttpTransportSE(SERVICE_URL); SERVICE_URL是webservice提供服务的url

HttpTransportSE ht = new HttpTransportSE(serviceURL);ht.debug=true;

 

3,实例化SoapObject对象:SoapObject soapObject = new SoapObject(SERVICE_NAMESPACE, methodName); 第一个参数表示WebService的命名空间,可以从WSDL文档中找到WebService的命名空间。第二个参数表示要调用的WebService方法名。

SoapObject request = new SoapObject(nameSpace, methodName);

 

4,使用SOAP1.1协议创建Envelop对象:SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 设置SOAP协议的版本号,根据服务端WebService的版本号设置。

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);


5,设置调用方法的参数值,如果没有参数,可以省略:例如soapObject.addProperty("name", value);

if(param_list!=null){    for(int i=0;i<param_list.length();i++)    {        request.addProperty(param_list.getJSONObject(i).getString("name"),param_list.getJSONObject(i).getString("value"));    }}

 

6,设置与.NET提供的webservice保持较好的兼容性

 envelope.dotNet=true;

 

7,记得设置bodyout属性 envelope.bodyOut = soapObject;

envelope.bodyOut=request;envelope.setOutputSoapObject(request);

 

8,调用webservice:ht.call(SERVICE_NAMESPACE+methodName, envelope);

ht.call(nameSpace+methodName, envelope);

 

9,解析服务器响应的SOAP消息

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

 

附上建进整理的源代码:

/** * 调用服务器方法 * @param nameSpace     要调用WebServices的命名空间 * @param serviceURL    要调用WebServices的绝对地址 * @param methodName    要调用WebServices哪个方法名 * @param param_list    要输入的参数数组,没有写null * @return    返回服务器数据 * @throws JSONException 参数出错 */private String Get_WebService_1_String(String nameSpace,String serviceURL,String methodName,JSONArray param_list) throws JSONException{    try {        SoapObject request = new SoapObject(nameSpace, methodName);            if(param_list!=null){            for(int i=0;i<param_list.length();i++)            {                request.addProperty(param_list.getJSONObject(i).getString("name"),param_list.getJSONObject(i).getString("value"));            }        }        Log.d("Informacation", "参数正确");        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);        envelope.bodyOut=request;        envelope.dotNet=true;        envelope.setOutputSoapObject(request);         HttpTransportSE ht = new HttpTransportSE(serviceURL);        ht.debug=true;        Log.d("Informacation","网络是否开启,访问地址为:"+serviceURL);        ht.call(nameSpace+methodName, envelope);        SoapObject result =(SoapObject) envelope.bodyIn;        return result.getProperty(0).toString();    }     catch (XmlPullParserException e) {        // TODO 自动生成的 catch 块        Log.d("Informacation","XmlPullParserException错误:"+e.toString());    }catch(IOException e)    {        Log.d("Informacation","IO错误:"+e.toString());    }    catch(Exception e)    {        Log.d("Informacation","有可能是方法里面参数不对,或者没有这个方法,错误原因:"+e.toString());    }    return "";}

 

上面这个便是主要实现远程调用webservice的代码,其他实现在activity中完成即可,但是这里也会涉及到一个问题,就是Android多线程问题,在调用webservice时,为了防止ANR的出现,不能在主线程中进行,需要另开子线程执行,,因为子线程涉及到UI更新,Android主线程是线程不安全的

另外开一个线程来调用webservice

/** * 调用的服务为WebService_1 * @param context       要传入Activity * @param message       用于返回的消息 * @param methodName    传入的方法名称 * @param param_list    要传入方法的参数和值,如 [{‘name‘:‘方法名‘,‘value‘:‘方法值‘},{‘name‘:‘2‘,‘value‘:‘2‘}] */public void Get_WebService_1_Connect(Message message,String methodName,JSONArray param_list){    this.Target_Message=message;    this.NameSpace=context_this.getString(R.string.nameSpace);    this.MethodName=methodName;    this.Param_List=param_list;    if(!isNetworkConnected()){        Toast.makeText(context_this,"网络没有开启,请开启网络", Toast.LENGTH_LONG).show();        return ;    }    Thread thread=new Thread(runable);    thread.start();}

 

如下为匿名线程类

/** * 线程,把服务器返回的数据发送出去 */Runnable runable=new Runnable(){    @Override    public void run() {        try {            String value= Get_WebService_1_String(SoapConnect.this.NameSpace,SoapConnect.this.ServiceURL,SoapConnect.this.MethodName
        ,SoapConnect.this.Param_List); Bundle bundle=Target_Message.getData(); bundle.putString("Data", value); Target_Message.setData(bundle); Target_Message.sendToTarget(); } catch (Exception e) { Log.d("Informacation", "线程出错"); } }};

 

接下来只要编写上面编写的调用webservice的方法和编写handle重写handleMessage方法可以实现调用完成后对数据的处理

编写的调用webservice的方法

/** * 远程调用 *  * @param Local_MethodName 要返回的本地方法 * @param Remote_MethodName 要调用远程的方法 * @param Param_List 要调用远程方法的参数 */private void Remote_Calls(MethodName Local_MethodName,int Remote_MethodName, JSONArray Param_List) {    // 调用服务器方法    SoapConnect sc = new SoapConnect(DocumentBoxCenterListActivity.this);    myHandler handler = new myHandler();    Message message = handler.obtainMessage();    Bundle bundle = new Bundle();    bundle.putString("MethodName", Local_MethodName.toString());    message.setData(bundle);    sc.Get_WebService_1_Connect(            message, DocumentBoxCenterListActivity.this.getString(Remote_MethodName), Param_List);}

 

编写handle重写handleMessage方法可以实现调用完成后对数据的处理

/** * 自定义Handler 专门对这个Activity处理服务器传送回来的数据 */class myHandler extends Handler {    @Override    public void handleMessage(Message msg) {        Log.e("Informacation", "数据正确返回");        if (msg.getData().get("MethodName") == MethodName.GetDocumentBoxs_Remote.toString()) {            GetDocumentBoxs_Remote(msg.getData().getString("Data"));        }        super.handleMessage(msg);    }};