Использование сервиса localhost WCF с использованием kSOAP2 в эмуляторе - PullRequest
3 голосов
/ 30 июня 2011

Я воткнул голову об эту стену уже пару дней, поэтому любая помощь очень ценится.

Сначала немного фона. Я опытный разработчик WindowsMobile, работающий на Android, поэтому я новичок в Java, Android и даже в WCF. Я провел много исследований о том, как использовать приложения WCF в Android с помощью kSOAP2, но независимо от того, что я делаю, лучше всего можно придумать ошибку сокета в Android из-за истечения времени ожидания.

Сначала я создал приложение веб-службы в Visual Studio 2008, которое не требует параметров и просто отвечает строковым значением. Код веб-сервиса выглядит следующим образом:

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.config.

Когда я запускаю сервис, он открывает мой браузер и указывает на следующий URL:

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 ]

5 голосов
/ 22 июля 2011

Хорошо, я наконец-то разобрался в своих проблемах.Было несколько факторов, которые можно ожидать от кого-то нового в этих технологиях.Надеюсь, мои ошибки сэкономят время другим.

Первая проблема, с которой я столкнулся, была ошибка параметра в моем коде.Строка

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

была неправильной в том смысле, что в ней должно было быть указано пространство имен для моего веб-сервиса, а затем имя метода.Таким образом, я изменил эту строку на следующую:

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)

Это сообщение широко распространено в Интернете, но ни одно из найденных мной решений не сработало для меня.После большого количества проб и ошибок я нашел свою конкретную проблему.Мой веб-сервис создан в Visual Studio 2008, и я тестирую его, просто запустив в Visual Studio, а затем пытаюсь использовать его из моего эмулятора Android.Оказывается, в IIS «песочницы» VS2008 есть параметр безопасности, который отклоняет любые запросы, выходящие за пределы локального ПК, и, очевидно, эмулятор не считается локальным ПК.

Чтобы исправить эту проблему, я воспользовалсяследующие действия в Visual Studio 2008:

  1. Выйдите из Visual Studio и откройте его с правами администратора (я использую Windows 7).
  2. Открыв свой проект, я просмотрел свойства проекта.
  3. На вкладке «Интернет» я изменил радиокнопку раздела «Серверы» на «Использовать локальный веб-сервер IIS», ввел «http://localhost/Sample" в качестве URL-адреса моего проекта и нажал кнопку« Создать виртуальный каталог ».

После выполнения этих шагов я снова запустил свой веб-сервис, запустил свое приложение Android в эмуляторе и, наконец, получил строку, которая выдавала исключение все время. Однако на этот раз следующая строка вызвалаисключение. Еще одна моральная победа и шаг вперед. Это новое исключение было:

org.ksoap2.serialization.SoapPrimitive

Быстрый поиск в Google решил это за mе.Строки

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

в моем исходном коде нужно было изменить на следующее:

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

После этого изменения у меня было рабочее приложение.

Finalрабочий код

веб-служба (созданная в Visual Studio 2008 и работающая на локальном веб-сервере IIS в соответствии с настройками в свойствах проекта)

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 голос
/ 18 июля 2011

Я только что боролся с этой проблемой. Для доступа к локальному хосту на вашем компьютере вам необходим IP-адрес 10.0.2.2. Я нашел ответ здесь. http://developer.android.com/resources/faq/commontasks.html#localhostalias. Теперь у меня нет тайм-аута сокета, но я получаю исключение XMLPullParserException, на котором я застрял.

...