现在的移动设备根本不可能离得开网络连接,数据的交换。最近学习的是在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); } };
Android使用ksoap2-android调用WebService