如何在安卓设备上调用SOAP网络服务

569

我在寻找如何在Android中调用标准的SOAP/WSDL Web服务方面遇到了很多问题。我找到的大部分文档要么非常复杂,要么只是提到了"kSoap2",然后让你手动解析所有内容使用SAX。好吧,这没关系,但是它是2008年的事情,所以我想应该有一些好的库可以用于调用标准Web服务。

这个Web服务基本上只是在NetBeans中创建的一个服务。我想要有IDE支持生成plumbing类。我只需要最简单/最优雅的方式来从基于Android的手机联系WSDL的Web服务。


这是一个非常好的关于在Android中使用SOAP的链接:如何使用SOAP在Android中调用Web服务 - Jainendra
如果之前熟悉MS VS,使用Mono for Android将解决许多与数据服务和Web服务相关的问题,一切都简单而快速地开发。 此外,对于不熟悉C#(代码非常类似于Java)的人来说,所有库都具有相同的方法,一些函数被替换为属性,因此名称几乎相同,之前在Android上使用Java编写的人可以非常轻松地利用他们的经验编写C#代码。 - Eugene Bosikov
请查看以下链接,其中有一个详细的示例,介绍了如何在Android中使用Ksoap2访问Web服务从Android访问Web服务 - Fred Ondieki
我相信使用Xamarin/C#和.Net Core是可能的。请参考https://blogs.msdn.microsoft.com/webdev/2016/05/25/announcing-wcf-connected-service-for-net-core-rc2-and-asp-net-core-rc2/。 - Vahid Amiri
这个由Spring提供的工具看起来很有前途。 - Louis
管理员们又搞出了更多毫无意义的混乱... - undefined
26个回答

252

Android没有提供任何类型的SOAP库。你可以编写自己的库,或者使用像kSOAP 2这样的库。正如你所指出的那样,其他人已经能够在他们自己的项目中编译和使用kSOAP2,但我并没有这样做过。

迄今为止,Google似乎对将SOAP库添加到Android中没有太大兴趣。我怀疑这是因为他们更愿意支持Web服务中当前潮流,即支持基于REST的服务,并使用JSON作为数据封装格式,或者使用XMPP进行通信。但这只是推测。

目前,在Android上实现基于XML的Web服务稍微有些困难。我不了解NetBeans,无法评论那里可用的工具,但我同意应该提供更好的库。可能XmlPullParser可以避免使用SAX,但我对此了解甚少。


7
是的,我认为我需要建立一个REST代理。谷歌没有提供SOAP支持似乎非常奇怪。我尝试了kSoap方法,但它并不是一个严肃的替代方案。最多只能说是一个难看的帽子,需要在新闻组中进行大量搜索。 - BobbyShaftoe
19
原因可能是SOAP过于冗长,不太适合移动计算的约束条件。 - Neil
94
如果有人能建议最佳替代方案来使用Android应用程序调用Web服务,那么这个答案将会更好。一旦人们找到这个问题并阅读它,大多数人都会寻找这样的信息。 - MGOwen
4
与 JSON 等更为简洁的格式相比,SOAP 处理对内存和处理器的需求也更加密集。 - Jeremy Edwards
3
@MGOwen 我能想到的最好的替代方案是使用代理。实现一个RESTful接口,通过WSDL2Java代理SOAP信封。 - user4903
显示剩余2条评论

99

org.apache.http.impl.client.DefaultHttpClient 默认包含在Android SDK中。这将使您连接到WSDL。

HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet("http://www.example.com/" + URL);
HttpResponse response = httpClient.execute(httpGet, localContext);

5
是的,这条路线需要我手动解析每个部分,而无法采用面向对象的方法。 - BobbyShaftoe
94
你的意思是你不会得到免费的午餐。手动解析与面向对象编程无关。我可以用最先进的工具HB1铅笔在纸上解析所有内容,但它仍然是面向对象的。 - Neil
8
我认为“OO”在这里指的是Java-XML绑定。在这种方法中,解析响应的下一步将是什么?如果它有数百个元素,组织成树状结构怎么办? - rustyx
12
顺便说一下,如果你想成功使用SOAP,我希望你至少发送一个HTTP POST请求而不是GET请求。另外,Accept和SOAPAction头在哪里?如果你真的想要自己动手实现,需要更多的代码才能调用 SOAP 服务。 - rustyx
6
如果情况迫使你使用 SOAP,比如 Web 服务器使用 SOAP,而你无法控制这一点,该怎么办? - Bjarke Freund-Hansen
显示剩余4条评论

60

确实,由于SOAP的开销较大,它不是与移动设备进行数据交换的最佳选择。但是,在某些情况下,您可能会发现自己无法控制服务器输出格式。

因此,如果必须坚持使用SOAP,则可以在这里找到专为Android修补的kSOAP2库:
http://code.google.com/p/ksoap2-android/


31
为了从移动设备(尤其是 Android 手机)调用 Web 服务,我使用了一种非常简单的方法。我没有使用任何 Web 服务客户端 API 来尝试调用 Web 服务。我的方法如下:
  1. 使用 Java 标准 API 的 HttpURLConnection 建立一个简单的 HTTP 连接。
  2. 创建 SOAP 请求。(您可以使用 SOAPUI 创建 SOAP 请求。)
  3. 将 doOutPut 标志设置为 true。
  4. 设置 HTTP 头值,例如 content-length、Content type 和 User-agent。不要忘记将 Content-length 值设置为必填项。
  5. 将整个 SOAP 请求写入输出流中。
  6. 调用方法以建立连接并接收响应(在我的情况下,我使用了 getResponseCode)。
  7. 如果您接收到的响应代码为200,则表示您已成功调用 Web 服务。
  8. 现在,在同一 HTTP 连接上获取输入流并接收字符串对象。此字符串对象是 SOAP 响应。
  9. 如果响应代码不是200,则在相同的 HTTP 对象上获取 ErrorInput 流并接收任何错误。
  10. 使用 SAXParser(在我的情况下)或 DOMParaser 或任何其他解析机制解析接收到的响应。
我已经为 Android 手机实现了此过程,它正在成功运行。即使响应超过700 KB,我也能够解析响应。

29

SOAP技术在Android(或移动设备)上使用是不太适合的,因为需要处理/解析开销。REST服务是一种更轻量级的解决方案,这是我建议的做法。 Android自带SAX解析器,使用起来相对容易。如果你绝对需要在移动设备上处理/解析SOAP,那么我为你感到难过,我能提供的最好建议就是不要使用SOAP。


3
那些强迫开发者使用SOAP服务而不是REST API的人会有一个特殊的地方在地狱里。 - Hitesh Sahu

24

大约一年前,我在阅读这篇帖子时想要弄清楚如何在Android上进行SOAP调用。建议使用HttpClient构建自己的库后,我创建了自己的Android SOAP库:

IceSoap

基本上,它允许您通过一个简单的Java API来构建信封并发送,接着自动解析为您通过XPath定义的对象... 例如:

<Dictionary>
    <Id></Id>
    <Name></Name>
</Dictionary>

变成:

@XMLObject("//Dictionary")
public class Dictionary {
    @XMLField("Id")
    private String id;

    @XMLField("Name")
    private String name;
}

我最初是为自己的项目使用它,但我认为它可能有助于其他人,因此我花了一些时间将其分离并进行了文档化。如果你们这些在谷歌搜索“SOAP Android”时偶然发现这个帖子的可怜人能够尝试并从中受益,我会非常高兴的。


你在IceSoap上使用过会话认证吗? - Adnen Chouibi

24
不要忘记在你的项目中添加ksoap2.jar,并在AndroidManifest文件中添加INTERNET权限。
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class WebserviceActivity extends Activity {

    private static final String NAMESPACE = "https://api.authorize.net/soap/v1/";
    private static final String URL ="https://apitest.authorize.net/soap/v1/Service.asmx?wsdl"; 
    private static final String SOAP_ACTION = "https://api.authorize.net/soap/v1/AuthenticateTest";
    private static final String METHOD_NAME = "AuthenticateTest";
    private TextView lblResult;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        lblResult = (TextView) findViewById(R.id.tv);

        SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); 
        request.addProperty("name","44vmMAYrhjfhj66fhJN");
        request.addProperty("transactionKey","9MDQ7fghjghjh53H48k7e7n");
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
        envelope.setOutputSoapObject(request);
        HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
        try {
            androidHttpTransport.call(SOAP_ACTION, envelope);

            //SoapPrimitive  resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
            // SoapPrimitive  resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
            SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn;


            lblResult.setText(resultsRequestSOAP.toString());
            System.out.println("Response::"+resultsRequestSOAP.toString());


        } catch (Exception e) {
            System.out.println("Error"+e);
        }

    }
}

1
HttpTransportSE 这个类在哪里可以获取到? - Noman
你好,我正在使用你的代码,但是出现了以下错误:Response::AuthenticateTestResponse{AuthenticateTestResult=anyType{resultCode=Error; messages=anyType{MessagesTypeMessage=anyType{code=E00014; text=Merchant Authentication is required.; }; }; }; } 请问你能帮我解决吗? - Hasmukh
嗨,阿米特,我也是阿米特。你能告诉我在我们收到响应时如何比较响应是否成功以及要检查响应的条件和方式吗? - Amitsharma
如何在请求属性的XML中添加数组? - droidster.me

21

我曾经和KSOAP有过交集;我选择了一个比较简单的方法。

给定一个WSDL文件,为每个请求创建SOAP请求模板(例如:使用SOAP UI),然后在代码中替换要传递的值。使用DefaultHttpClient实例将此数据POST到服务端点并获取响应流。使用XML Pull解析器解析响应流。


18

4
终于在反复提及kSoap或SAX之后得到第一个有用的回答。 - rustyx
我尝试了演示版,对于一个简单的服务来说并没有起作用。这不值得花费那么多的$$$$。 - Tushar

16

我已经为Android平台创建了一个新的SOAP客户端。它使用了一个JAX-WS生成的接口,但目前只是一个概念验证。

如果您有兴趣,请尝试这个示例并/或查看AndroidSOAP的源代码。


1
我很荣幸参加了你在JUM XVII.布达佩斯关于Android的演讲。继续保持好工作! - pcjuzer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接