在模拟器中使用kSOAP2使用localhost WCF服务

时间:2011-06-30 16:32:36

标签: android wcf ksoap2

我已经把头撞到了这堵墙上了几天,所以非常感谢任何帮助。

首先是一些背景知识。我是一位经验丰富的WindowsMo​​bile开发人员,因此我是Java,Android甚至WCF的老手。我已经做了很多关于如何使用kSOAP2在Android中使用WCF应用程序的研究,但无论我做得最好,我都能想到因为超时而在Android中出现套接字错误。

首先,我在Visual Studio 2008中创建了一个不需要参数的Web服务应用程序,只需使用字符串值进行响应。 Web服务代码如下:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;

namespace Sample
{
    [WebService(Namespace = "http://sample.com/")]
    public class Service1 : System.Web.Services.WebService
    {
        [WebMethod]
        public string SayHello()
        {
            return "Hello, Android. From your friend, WCF";
        }
    }
}

对于此Web服务,我没有调整任何其他设置或对Web.config文件进行任何修改。

当我运行该服务时,它会打开我的浏览器并指向以下网址:

http://localhost:61554/Service1.asmx

接下来,我跳入Eclipse并创建了一个简单的Android项目来使用WCF服务。对于初学者,我更改了AndroidManifest.xml文件并将此语句添加到其中:

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

现在我的Android类的代码应该可以解决这个问题:

package com.sample;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import org.ksoap2.*;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.*;

public class Sample extends Activity {
    TextView result;

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

        result = (TextView)findViewById(R.id.textViewResult);

        try {
            SoapObject Request = new SoapObject("http://sample.com/", "SayHello");

            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(Request);

            HttpTransportSE androidHttpTransport = new HttpTransportSE("http://192.168.1.72:61554/Service1.asmx");

            androidHttpTransport.call("http://192.168.1.72:61554/SayHello", envelope);
            SoapObject response = (SoapObject)envelope.getResponse();
            String resultValue =  response.getProperty(0).toString();

            result.setText(resultValue);            
        } 
        catch (Exception e) {
            result.setText(e.getMessage());
        }
    }
}

给我错误的代码行是:

androidHttpTransport.call("http://192.168.1.72:61554/SayHello", envelope);

当在模拟器中运行时,代码到达该行,暂停一两分钟,然后进入catch块并带有超时异常。

关于我在这里可能缺少的任何想法?感谢您的帮助。

2 个答案:

答案 0 :(得分:5)

好的,我终于想出了我的问题。对于这些技术的新手,您可能会遇到几个因素。希望我的错误会在一段时间内拯救他人。

我遇到的第一个问题是我的代码中出现参数错误。这条线

androidHttpTransport.call("http://192.168.1.72:61554/SayHello", envelope);

不正确,因为它应该列出我的Web服务的命名空间,后跟方法名称。所以我改变了这一点:

androidHttpTransport.call("http://sample.com/SayHello", envelope);

在这次改变之后我仍然让这条线抛出一个异常,但现在我得到了一个不同的例外,这至少是道德上的胜利。新的例外说:

expected START_TAG{http://schemas.xmlsoap.org/soap/envelope/} Envelope(position:START_TAG<html>@1:6 in java.io.InputStreamReader@d3el2cc4)

此消息在互联网上猖獗,但我找到的解决方案都没有为我工作。经过大量的反复试验,我发现了我的特殊问题。我的Web服务是在Visual Studio 2008中创建的,我只是通过在Visual Studio中运行它然后尝试从我的Android模拟器中使用它来测试它。事实证明,VS2008“沙盒”IIS中存在一个安全设置,拒绝本地PC之外的任何请求 - 显然模拟器不被视为本地PC。

为了纠正这个问题,我在Visual Studio 2008中采取了以下步骤:

  1. 退出Visual Studio并使用管理权限打开它(我使用的是Windows 7)。
  2. 打开我的项目后,我查看了项目属性。
  3. 在“Web”选项卡上,我将“服务器”部分的单选按钮更改为“使用本地IIS Web服务器”,为我的项目URL输入“http:// localhost / Sample”,然后单击“创建虚拟目录”按钮
  4. 完成这些步骤后,我再次运行我的Web服务,在模拟器中启动了我的Android应用程序,最后得到了一直抛出异常的行。然而,这一次,下一行抛出异常。另一个道德胜利又更近了一步。这个新例外是:

    org.ksoap2.serialization.SoapPrimitive
    

    Google快速搜索为我解决了这个问题。行

    SoapObject response = (SoapObject)envelope.getResponse();
    String resultValue =  response.getProperty(0).toString();
    

    在原始代码中需要更改为:

    SoapPrimitive response = (SoapPrimitive)envelope.getResponse();
    String resultValue = response.toString();
    

    在那次改变之后,我有了一个有效的应用程序。

    最终工作代码

    Web服务(在Visual Studio 2008中创建并在项目属性中配置的本地IIS Web服务器上运行)

    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.Web.Services;
    
    namespace Sample {
        [WebService(Namespace = "http://sample.com/")]
        public class Service1 : System.Web.Services.WebService {
            [WebMethod]
            public string SayHello() {
                return "Hello, Android. From your friend, WCF";
            }
        }
    }
    

    Android类

    package com.sample;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    
    import org.ksoap2.*;
    import org.ksoap2.serialization.SoapObject;
    import org.ksoap2.serialization.SoapSerializationEnvelope;
    import org.ksoap2.transport.*;
    import org.ksoap2.serialization.SoapPrimitive;
    
    public class Sample extends Activity {
    TextView result;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            result = (TextView)findViewById(R.id.textViewResult);
    
            final String SOAP_ACTION = "http://sample.com/SayHello";
            final String METHOD_NAME = "SayHello";
            final String NAMESPACE = "http://sample.com/";
            final String URL = "http://192.168.1.72/Sample/Service1.asmx";
    
    
            try {
                SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
    
                SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
                envelope.dotNet = true;
                envelope.setOutputSoapObject(request);
    
                HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
    
                androidHttpTransport.call(SOAP_ACTION, envelope);
                SoapPrimitive response = (SoapPrimitive)envelope.getResponse();
                String resultValue = response.toString();
    
                result.setText(resultValue);            
            } 
            catch (Exception e) {
                result.setText(e.getMessage());
            }
        }
    }
    

答案 1 :(得分:1)

我只是在努力解决这个问题。要访问PC上的本地主机,您需要IP地址10.0.2.2。我在这里找到了答案。 http://developer.android.com/resources/faq/commontasks.html#localhostalias。现在我没有得到套接字超时,但是我得到了一个XMLPullParserException,我被困在了。