美文网首页
Android通过SOAP调用Webservice(.Net)接

Android通过SOAP调用Webservice(.Net)接

作者: Killshadow | 来源:发表于2019-04-03 12:21 被阅读0次

    0x00 前言(废话)

    项目中有遇到登录验证机制, 用户校验机制一般都是在服务器校验的, 本博客主要介绍Android的WebService调用方法, 登录验证机制以后有机会再另起文章.

    效果图如下:

    0x10 申请权限

    AndroidManifest.xml中, 给APP添加网络权限:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:dist="http://schemas.android.com/apk/distribution"
              package="com.xxx.xxx">
        <!-- 主要是下面这一行 -->
        <uses-permission android:name="android.permission.INTERNET"/>
        ...
    </manifest>
    

    0x20 载入SOAP的jar包

    1. 官网下载最新的soap包, 在该页面的下方:

    2. 下载好之后, 在Project视图把jar包添加到libs目录, 如下: 直接copy到该目录即可
    3. 在Android Studio中添加依赖: File --> Project Structure... --> Modules --> app -->Dependencies:

      添加libs上的jar包到依赖
    4. 如果添加完成, 能在appbuild.gradledependencies看到:

    dependencies {
        ...
        implementation files('libs/ksoap2-android-assembly-3.6.4-jar-with-dependencies.jar')
    }
    

    0x30 访问接口

    1. WebService接口

    推荐一个比较知名的测试接口: WeatherWS, 里面有6个方法供我们调用, 包括有输入参数/无输入参数:


    在这里我拿第一个调用接口(方法)来举例, 点进getRegionCountry接口之后, 能看到各种SOAP版本的POSTGET请求:
    POST /WebServices/WeatherWS.asmx HTTP/1.1
    Host: ws.webxml.com.cn
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    SOAPAction: "http://WebXml.com.cn/getRegionCountry"
    
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <getRegionCountry xmlns="http://WebXml.com.cn/" />
      </soap:Body>
    </soap:Envelope>
    

    2. 定义访问接口的类

    ① 定义常量

    我们需要在Android Studio中的类中定义如下四个字符串常量:

    private static String SOAP_ACTION="http://WebXml.com.cn/getRegionCountry";
    private static String NAMESPACE="http://WebXml.com.cn/";
    private static String METHOD_NAME="getRegionCountry";
    private static String URL="http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?WSDL";
    
    • SOAP_ACTION: 顾名思义, 就是要访问的动作, 实际上就是NAMESPACE + METHOD_NAME.
    • NAMESPACE: 命名空间, 学过C++的同学应该比较熟悉(类似于using namespace std;), 就是一个方法所在的名字空间.
    • METHOD_NAME: 方法名, 即我们要调用的接口名(方法名).
    • URL: WebService的地址.

    ② 定义访问方法

    private SoapObject getResultFromWebService() {
        // define webservice using namespace and it's method name
        SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
        // if this methon need input parameter, we can use addProperty
        // request.addProperty("theCityCode", "深圳");
    
        // generate the SOAP-request-information of WebService method which we want to call
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    //        envelope.bodyOut = request;
    //        envelope.dotNet = true;
        envelope.setOutputSoapObject(request);
        try {
            // create HttpTransportSE object, it can define WebService WSDL Document by URL
            HttpTransportSE transportSE = new HttpTransportSE(URL);
            transportSE.call(SOAP_ACTION, envelope);
            SoapObject result = (SoapObject) envelope.bodyIn;
            SoapObject test = (SoapObject) result.getProperty(0);
            return test;
        } catch (Exception e) {
            Log.i(TAG, "Connect network wrong!");
            e.printStackTrace();
        }
        return null;
    }
    

    ③ 多线程调用

    我们需要开一个线程去掉用上面的方法, 不要用主线程, 才不会影响到界面状态:

    这里想到有两种方式:

    • AsyncTask异步调用
    • 重写一个线程类, 继承自Thread.
      如果用第一种方法, 比较简单, 直接在doInBackground()方法中调用即可, 但是较难复用.
      如果用第二种方法, 则代码的封装性比较好, 耦合性低, 但是较为复杂. 这里我先用第一种方法示例.
    class LoginToServerTask extends AsyncTask<Void, Integer, Boolean> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
    
        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
    
            try {
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < result.getPropertyCount(); i++) {
                    builder.append(result.getProperty(i));
                }
                Toast.makeText(getBaseContext(), builder.toString(), Toast.LENGTH_SHORT).show();
            } catch (Exception e) {
                Toast.makeText(getBaseContext(),getResources().
                        getText(R.string.str_no_response_check_network),Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }
        }
    
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }
    
        @Override
        protected Boolean doInBackground(Void... voids) {
            result = getResultFromWebService();
            return null;
        }
    }
    

    ④ 在主线程开子线程

    这里我们在onCreate()方法中调用上面的线程, 一般写在Button(或其他组件)的监听事件里:

    mLoginBt.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    new LoginToServerTask().execute();
                }
            });
    

    ⑤ 补充: 带参数接口调用

    首先, 我们需要去WSDL文档查找一下接口参数类型, 参数的数量, 我们找到的getSupportCityString需要输入一个参数, 如下:

    POST /WebServices/WeatherWS.asmx HTTP/1.1
    Host: ws.webxml.com.cn
    Content-Type: text/xml; charset=utf-8
    Content-Length: length
    SOAPAction: "http://WebXml.com.cn/getSupportCityString"
    
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <getSupportCityString xmlns="http://WebXml.com.cn/">
          <!-- 下面的即为输入参数, theRegionCode表示参数的名称, string表示参数的类型-->
          <theRegionCode>string</theRegionCode>
        </getSupportCityString>
      </soap:Body>
    </soap:Envelope>
    

    带参数的需要给soapObject实例化的对象添加参数, 用addProperty, 方法如下:

    request.addProperty("theRegionCode", "日本");
    
    private static String SOAP_ACTION = "http://WebXml.com.cn/getSupportCityString";
    private static String NAMESPACE = "http://WebXml.com.cn/";
    private static String METHOD_NAME="getSupportCityString";
    private static String URL="http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?WSDL";
    
    private SoapObject getResultFromWebService(String volId, String passWd) {
        // define webservice using namespace and it's method name
        SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
        // if this methon need input parameter, we can use addProperty
        request.addProperty("theRegionCode", "日本");
    
        // generate the SOAP-request-information of WebService method which we want to call
        // 设置SOAP协议的版本号, 根据服务端WebService的版本号设置
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.bodyOut = request;
        envelope.dotNet = true;
        envelope.setOutputSoapObject(request);
        try {
            // create HttpTransportSE object, it can define WebService WSDL Document by URL
            HttpTransportSE transportSE = new HttpTransportSE(URL);
            transportSE.call(SOAP_ACTION, envelope);
            SoapObject result = (SoapObject) envelope.bodyIn;
            SoapObject test = (SoapObject) result.getProperty(0);
            return test;
        } catch (Exception e) {
            Log.i(TAG, "Connect network wrong!");
            e.printStackTrace();
        }
        return null;
    }
    

    0x40 术语解释

    WSDL

    WSDL(Web服务描述语言,Web Services Description Language)是为描述Web服务发布的XML格式. 摘自维基百科

    • WSDL描述Web服务的公共接口。这个基于XML的接口描述了如何与Web服务通讯和使用的服务, 也就是描述与目录中列出的Web服务进行交互时需要绑定的协议和信息格式. 通常采用抽象语言描述该服务支持的操作和信息, 使用的时候再将实际的网络协议和信息格式绑定给该服务.
    • 我们用.Net开发的网站, 如果开放了接口, 就需要声明这些接口的输入参数, 输出等, WSDL就是描述了这些内容. 如: http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?WSDL

    SOAP

    SOAP(Simple Object Access Protocol的首字母缩写,即简单对象访问协议)是交换数据的一种协议规范, 在计算机网络Web服务(web service)中使用, 交换带结构的信息。摘自维基百科

    • 用XML格式来传递信息.
    • 举例: 一个SOAP消息可以发送到一个具有Web Service功能的Web站点,例如,一个含有房价信息的数据库,消息的参数中标明这是一个查询消息,此站点将返回一个XML格式的信息,其中包含了查询结果(价格,位置,特点,或者其他信息)。由于数据是用一种标准化的可分析的结构来传递的,所以可以直接被第三方站点所利用。
    • 协议规范由4部分组成:

    SOAP封装(envelope),它定义了一个框架,描述消息中的内容是什么,是谁发送的,谁应当接受并处理它以及如何处理它们;
    SOAP编码规则(encoding rules),它定义了一种序列化的机制,用于表示应用程序需要使用的数据类型的实例;
    SOAP RPC表示(RPC representation),它定义了一个协定,用于表示远程过程调用和应答;
    SOAP绑定(binding),它定义了SOAP使用哪种协议交换信息。使用HTTP/TCP/UDP协议都可以。

    相关文章

      网友评论

          本文标题:Android通过SOAP调用Webservice(.Net)接

          本文链接:https://www.haomeiwen.com/subject/ynrabqtx.html