ksoap2-android开发Android SOAP客户端

辛苦堆砌,转载请注明出处,谢谢!

最近项目需要使用SOAP进行WebService通信,采用了google提供的ksoap2-android进行开发,做一下记录。首先,使用Python创建了一个简单的基于Soap的服务,使用的是spyne模块,代码如下:

import logging
logging.basicConfig(level=logging.DEBUG)

from spyne import Application, rpc, ServiceBase, Unicode

from spyne import Iterable

from spyne.protocol.soap import Soap11

from spyne.server.wsgi import WsgiApplication

class HelloWorldService(ServiceBase):
    @rpc(Unicode, _returns=Unicode)
    def say_hello(ctx, name):
        return 'Hello, %s' % name

application = Application([HelloWorldService],
    tns='http://spyne.examples.hello/',
    in_protocol=Soap11(),
    out_protocol=Soap11()
)

if __name__ == '__main__':
    from wsgiref.simple_server import make_server

    wsgi_app = WsgiApplication(application)
    server = make_server('0.0.0.0', 8000, wsgi_app)
    server.serve_forever()

我们创建了一个叫做HelloWorldService的服务,其中有一个方法是say_hello,需要一个name参数,命名空间为http://spyne.examples.hello/,在命令行执行python hello_world_service.py即可启动服务。服务的wsdl在这里无关紧要了,我们已经能够知道必要的信息了,所以不再贴出来。


下面看看我们的Android程序,首先下载ksoap2-android包,放置在项目app/libs目录下,然后将包添加到依赖,不再赘述。下面看看代码,我们基于ksoap2-android做了一个工具类

package com.yjp.ksoap2demo;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;

import java.util.Map;

public class SoapCommunicator {

    private static final int TIMEOUT_MS = 10000;

    public static final String ERROR_PREFIX = "error_";
    public static final String ERROR_COMMON = ERROR_PREFIX + "common";
    public static final String ERROR_TIMEOUT = ERROR_PREFIX + "timeout";

    //用来判断是否call调用返回的是error
    public static boolean isError(String str) {
        return str.contains(ERROR_PREFIX);
    }

    public String call(String wsdlUrl, String namespace, String methodName, Map<String, Object> params) {

        try {
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            SoapObject request = new SoapObject(namespace, methodName);

            //设置参数
            if (params != null && !params.isEmpty()) {
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    PropertyInfo info = new PropertyInfo();
                    info.setNamespace(namespace);
                    info.setName(entry.getKey());
                    info.setValue(entry.getValue());
                    request.addProperty(info);
                }
            }

            envelope.setOutputSoapObject(request);
            HttpTransportSE ht = new HttpTransportSE(wsdlUrl, TIMEOUT_MS);
            ht.call(null, envelope);
            Object response = envelope.getResponse();
            if (response != null) {
                return response.toString();
            } else {
                return ERROR_COMMON;
            }
        } catch (Exception e) {
            e.printStackTrace();

            if (e instanceof java.net.SocketTimeoutException) {
                return ERROR_TIMEOUT;
            }

            return ERROR_COMMON;
        }
    }

}

需要注意的是这里的call方法是同步调用,我们如果界面不想被卡,调用时应当采用一定的异步机制,稍后在MainActivity会看到。我们先看一下我们的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    android:gravity="center"
    tools:context="com.yjp.ksoap2demo.MainActivity">

    <TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/send_request_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击发送请求"/>

</LinearLayout>

布局中有一个TextView用来显示响应的内容,点击按钮发起请求。MainActivity如下

package com.yjp.ksoap2demo;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    private TextView mContentTextView;
    private SoapAsyncTask mSoapAsyncTask;

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

        mContentTextView = (TextView) findViewById(R.id.content);
        Button sendRequestButton = (Button) findViewById(R.id.send_request_button);
        sendRequestButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mSoapAsyncTask = new SoapAsyncTask();
                mSoapAsyncTask.execute();
            }
        });
    }

    @Override
    protected void onStop() {
        super.onStop();
        mSoapAsyncTask.cancel(false);
    }

    private class SoapAsyncTask extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... voids) {
            SoapCommunicator communicator = new SoapCommunicator();
            Map<String, Object> params = new HashMap<>();
            params.put("name", "张三");

            //这里使用的局域网,要保证IP可访问
            String ret = communicator.call(
                    "http://192.168.6.27:8000/?wsdl",
                    "http://spyne.examples.hello/",
                    "say_hello",
                    params
            );

            return ret;
        }

        @Override
        protected void onPostExecute(String s) {
            if (SoapCommunicator.isError(s)) {
                mContentTextView.setText("请求错误");
            } else {
                mContentTextView.setText(s);
            }
        }
    }
}

我们使用了AsyncTask来实现异步机制,在doInBackground中调用了call方法,之后在MainActivity中使用了SoapAsyncTask,注意IP,配置为自己可访问的。


最后在manifest文件中添加权限,以使用网络

<uses-permission android:name="android.permission.INTERNET" />

如果可以访问服务,这样我们点击按钮时,就会显示Hello,张三




评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值