Android调用Tomcat+axis2发布的WebService常见问题

来源:互联网 发布:网站建设及优化 编辑:程序博客网 时间:2024/05/29 03:42

转载请注明出自zfhsandra的博客:http://blog.csdn.net/zfhsandra/article/details/78791632

最近在学习Android,想用Android调用自己发布的Webservice,花了两天时间才调出来。我完全是一个菜鸟吧,所以碰到的问题可能和大家不一样,参考了很多网上教程,但是跟我实际存在的问题相比都不全,或者重点不一样,有些问题还是通过比较代码分析出来的,所以决定自己写一个博文总结一下,也希望能帮到和我一样的,想使用Android和WebService的新手!

先把问题列出来吧,大家可以先自查一下
1. 使用Thread和handler调用WebService
2. 用ip地址而不是localhost访问主机,ip可能变化
3. axis2发布的WebService的url后缀为“?wsdl”
4. 对应的字符串一定要准确,否则调用失败,比如namespace要注意是“http://example”还是“http://example/”
5. Envelope.bodyin的返回结果可能是SoapFault也可能是SoapObject,针对两种情况处理返回结果
6. SoapEnvelop的版本和WebService要一致
7. 调用公共WebService时先确认网址有效
8. ksoap2包的版本问题
9.Manifest中使用Internet权限
10. 参数的对应问题

下面是详细讲解

1. 使用Thread和handler调用WebService

我用的sdk是25,我记得调试的时候看到过说新版的sdk不允许在主线程调用WebService,所以要引入线程,子线程又不可以修改UI,所以如果需要调用WebService并在UI中显示结果,就需要使用Thread和handler来调用。

2. 用ip地址而不是localhost访问主机

安卓机不可以识别localhost,要用ip地址来访问。模拟机的话直接能访问,真机的话还需要调一下防火墙,这里不细讲了。
另外还要注意本机ip是可能变化的,调用失败的时候可以检查一下url能不能再网页中打开,最好设置一下,使ip固定。

3. axis2发布的WebService的url后缀为“?wsdl”

我在之前完全是Java新手,WebService新手,目前还是在读学生,只有简单的C、C++、python基础,所以碰到了一些很脑残很简单的问题,求轻喷。比如说这里,在调用公共webservice的时候,很多代码里面有一句是envelop.dotNet = true,这句话是表示这个WebService是用.Net发布的,但是使用Tomcat+axis2发布的服务不用加上这句话。
而且,当服务不是dotNet发布的时候,服务的url是以?wsdl结尾的,要在EPR后面加上“?wsdl”的后缀。

4. namespace要注意是“http://example”还是“http://example/”

这个也是我一开始没注意的地方,后来返回出错的时候才发现namespace多打了一个‘/’,不过在调用公共WebService(www.webxml.com.cn)的时候,他们的namespace后面都有一个‘/’,我当时调用自己服务的时候就顺手加上了,后来发现有这个‘/’调用会出错,所以需要检查一下,url、namespace、method这些东西一定要跟你的服务完全对应,不然都是调用不出来的。


以上是到调用WebService之前可能存在的问题,你可以在调用的同时打印日志,查看是否调用成功。调用成功后,结果还可能出现问题。


5. Envelope.bodyin的返回结果可能是SoapFault也可能是SoapObject,针对两种情况处理返回结果

当引用返回错误结果的时候,继续用SoapObject = envelope.bodyin程序就会报错甚至崩溃,所以先判断一下bodyin的类型,再根据类型得到返回值。

    if ( envelope.bodyIn instanceof SoapFault){        SoapFault error = (SoapFault)envelope.bodyIn;        result = error.toString();    } else {        SoapObject object = (SoapObject) envelope.bodyIn;        // Get returned result        result = object.getProperty(0).toString();    }

下面是一些对我影响较小,但是其他博文中普遍提到的问题


6. SoapEnvelop的版本和WebService要一致

就是

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);

这句话,里面的VER11可以换成VER12,VER10,主要是为了跟webservice的版本一致,版本不一致会调用失败。就我不多的经验来说一般都是11。

7. 调用公共WebService时先确认网址有效

之前很多教程都比较老,提供的查询手机号码归属地的网址已经失效了,所以我一开始都调不对,后来才发现是网址失效的问题。原来的url是http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx,现在已经改成了http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx
在调用网址之前,可以现在浏览器打开url,看看是否有效。

8. ksoap2包的版本问题

有人提到ksoap2jar包3.0的版本没办法调用本地服务,我没试过,用2.5.4没问题

9.Manifest中使用Internet权限

在AndroidManifest中要有这个声明

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

这个就不多说了,每篇博文都要提一遍,但是实际操作中卡在这一环的应该也不多

10. 参数的对应问题

在我自己写的服务中,addProperty的时候,参数只要顺序一致,就能出结果,但是在调用手机号码归属地的时候,一定要和网页上给的参数一致,

rpc.addProperty("mobileCode", phoneEdit.getText().toString());

这里的mobileCode是跟网页一致的,不一致调用会出错。

结果展示

我这里是自己写了一个两数相加的简单的WebService,java代码如下

``` javapackage com.sean;public class Math {  public int add(int a, int b) {    return a + b;  }}

发布方式参照用Eclipse+axis2+tomcat进行web service部署
在MainActivity中对自己的服务和公共WebService中手机号码归属地查询进行调用,结果如下
本地服务调用结果
本地服务调用结果
公共服务调用结果
公共服务调用结果

代码展示

这里把MainActivity的代码贴出来

package com.demo.android.wstest;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import org.ksoap2.SoapEnvelope;import org.ksoap2.SoapFault;import org.ksoap2.serialization.SoapObject;import org.ksoap2.serialization.SoapSerializationEnvelope;import org.ksoap2.transport.HttpTransportSE;public class MainActivity extends AppCompatActivity {    public static final int MOBILECITY = 1;    public static final int ADDFUNC = 2;    private EditText aEditText;    private EditText bEditText;    private EditText phoneEdit;    private TextView resultView;    private Button queryButton;    private Button queryPhone;    String TAG = "mobile webservice";    String result;    String nameSpace;    String methodName;    String endPoint;    String soapAction;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        aEditText = (EditText)findViewById(R.id.a);        bEditText = (EditText)findViewById(R.id.b);        phoneEdit = (EditText)findViewById(R.id.phone);        resultView = (TextView)findViewById(R.id.result_text);        queryButton = (Button)findViewById(R.id.query_btn);        queryButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                new Thread(new Runnable() {                    @Override                    public void run() {                        setSoapInfo(ADDFUNC);                        getRemoteInfo(ADDFUNC);                    }                }).start();            }        });        queryPhone = (Button)findViewById(R.id.btn_phone);        queryPhone.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                new Thread(new Runnable() {                    @Override                    public void run() {                        setSoapInfo(MOBILECITY);                        getRemoteInfo(MOBILECITY);                    }                }).start();            }        });    }    private Handler handler = new Handler() {        public void handleMessage(Message msg) {            switch (msg.what){                case MOBILECITY:                    resultView.setText("result: \n" + result);                    break;                case ADDFUNC:                    resultView.setText("result: " + result);            }        }    };    private void setSoapInfo(int method){        switch (method){            case MOBILECITY:                nameSpace = "http://WebXml.com.cn/";                methodName = "getMobileCodeInfo";                endPoint = "http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx";                soapAction = "http://WebXml.com.cn/getMobileCodeInfo";                break;            case ADDFUNC:                nameSpace = "http://sean.com";                methodName = "add";                endPoint = "http://192.168.1.16:8080/axis2/services/WebServiceTest?wsdl";                soapAction = "http://sean.com/add";                break;        }    }    public void getRemoteInfo(int method) {        Message message = new Message();        message.what = method;        // 指定WebService的命名空间和调用的方法名        SoapObject rpc = new SoapObject(nameSpace, methodName);        // 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);        //设置传入参数        switch (method){            case MOBILECITY:                rpc.addProperty("mobileCode", phoneEdit.getText().toString());                rpc.addProperty("userID","");                envelope.dotNet = true;                break;            case ADDFUNC:                rpc.addProperty("a",getInt(aEditText));                rpc.addProperty("b",getInt(bEditText));                break;        }        HttpTransportSE transport = new HttpTransportSE(endPoint);        envelope.setOutputSoapObject(rpc);        try {            // Call WebService            transport.call(soapAction, envelope);            Log.d(TAG, "getRemoteInfo: call success");        } catch (Exception e) {            e.printStackTrace();            Log.d(TAG, "getRemoteInfo: call failed");            return;        }        // Get returned data        if ( envelope.bodyIn instanceof SoapFault){            SoapFault error = (SoapFault)envelope.bodyIn;            result = error.toString();        } else {            SoapObject object = (SoapObject) envelope.bodyIn;            // Get returned result            result = object.getProperty(0).toString();        }        handler.sendMessage(message);    }    private int getInt(EditText editText){        String number = editText.getText().toString();        if ( isNumeric(number)){            int num = Integer.valueOf(number);            return num;        } else {            Log.d(TAG, "getInt: error input!");            return 0;        }    }    public static boolean isNumeric(String str){        return str.matches("^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$");    }}

参考:
已解决:android 模拟器调用本地的webservice 引用不到
Android基础入门教程——7.4 Android调用WebService
Android 调用 WebService
Android平台调用WebService详解

原创粉丝点击