Oct
01

Работа с SOAP Web-сервисами в Android-приложениях

Всем время от времени хочется странного. Вот мне тоже захотелось такого. А именно – подружить Android-приложение с .NET Web-сервисом – такие сервисы и писать быстрее и доступ к ним потом можно получить из Windows Mobile и Windows Phone 7 без проблем – тоесть одним махом можно решить проблему работы с сервисом для различных мобильных платформ. И вот в этот раз я расскажу о том, как сделать чтобы все это заработало.

Подготовительный этап – Создание Web-сервиса

Для начала создадим простой .NET Web-сервис:
ISampleService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace SampleService
{
    [ServiceContract]
    public interface ISampleService
    {
        [OperationContract]
        double Add(double a, double b, String c);
    }
}

SampleService.asmx.cs

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

namespace WebService
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class SampleService : System.Web.Services.WebService
    {
        [WebMethod]
        public double Add(double a, double b, String c)
        {
            return a + b;
        }
    }
}

Затем установим его на Web-сервер (для примера я создал виртуальный каталог на локальном IIS сервисе и установил туда сервис прямо из Visual Studio. После этого URL сервиса у меня получился вот такой:

http://192.168.1.32/SampleService/SampleService.asmx

kSOAP2 – Библиотека для доступа к SOAP-сервисам под Android

Процесс создания Android-приложения описывать не буду. Скажу только ,что после создания приложения необходимо в него добавить библиоеку kSOAP2-Android, которую можно скачать здесь.

После того, как скачали дистрибутив, JAR файл библиотеки нужнно положить в подкаталог lib в каталоге с исходными кодами проекта, а затем в окне свойств проекта в разделе Java Build Path на вкладке Libraries с помощью кнопки Add JARs… добавить его в список используемых библиотек.

Библиотеку добавили, теперь можно начинать кодинг.

Кодинг

kSOAP2 для работы с сервисом необходимы 4 параметра:

  • URL сервиса
  • Имя пространства имен
  • Имя SOAP-операции
  • Имя метода

URL Web-сервиса мы знаем – это адрес ASMX файла

Имя пространства имен можно узнать если открыть в браузере URL Web-сервиса:

Дальше нам надо узнать имя SOAP-операции, а также имя метода. Их можно узнать из WSDL схемы:

Итак, с параметрами подключения разобрались. Поулчаем что-то вроде этого:

private static final String NAMESPACE = "http://tempuri.org/";
private static final String URL = "http://192.168.1.32/SampleService/SampleService.asmx";
private static final String SOAP_ACTION = "http://tempuri.org/Add";
private static final String METHOD_NAME = "Add";

Теперь надо как-то наш метод вызывать из приложения и передавать туда параметры.
Добавим на activity два текстовых поля, кнопку и поле для вывода результата:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:focusable="true" android:focusableInTouchMode="true">

<EditText android:layout_height="wrap_content"
			android:layout_width="fill_parent"
			android:layout_margin="5dip"
			android:id="@+id/Num1EditText"
			android:inputType="number"
			android:text="2"></EditText>
<EditText android:layout_height="wrap_content"
			android:layout_width="fill_parent"
			android:layout_marginBottom="5dip"
			android:layout_marginLeft="5dip"
			android:layout_marginRight="5dip"
			android:id="@+id/Num2EditText"
			android:inputType="number"
			android:text="3"></EditText>
<Button android:text="="
			android:layout_height="wrap_content"
			android:layout_width="fill_parent"
			android:layout_marginLeft="5dip"
			android:layout_marginRight="5dip"
			android:id="@+id/CallServiceButton"></Button>
<TextView android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:textSize="24dip"
			android:textStyle="bold"
			android:layout_marginLeft="7dip"
			android:layout_marginRight="7dip"
			android:gravity="fill_vertical|fill_horizontal"
			android:id="@+id/ResultTextView"></TextView>
</LinearLayout>

Ну вот, теперь пишем обработчик для кнопки, в котором вызываем Web-сервис.

	OnClickListener mCallServiceButtonListener = new OnClickListener() {

		@Override
		public void onClick(View v) {
			try
			{
				double a = Double.parseDouble(mNum1EditText.getText().toString());
				double b = Double.parseDouble(mNum2EditText.getText().toString());
				double result = callService(a, b);
				mResultTextView.setText(String.valueOf(result));
			}
			catch(Exception e) {
				e.printStackTrace();
				mResultTextView.setText(SOAPTest.this.getString(R.string.message_error));
			}
		}
	};

	double callService(double a, double b) throws Exception {
		double result = 0;
		do
		{
			SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

			PropertyInfo pa = new PropertyInfo();
			pa.setName("a");
			pa.setValue(new Double(a).toString());

			PropertyInfo pb = new PropertyInfo();
			pb.setName("b");
			pb.setValue(new Double(b).toString());

			PropertyInfo pc = new PropertyInfo();
			pc.setName("c");
			pc.setValue("test");

			request.addProperty(pa);
			request.addProperty(pb);
			request.addProperty(pc);

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

			envelope.setOutputSoapObject(request);
			HttpTransportSE androidHttpTransport = new AndroidHttpTransport(URL);
			androidHttpTransport.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"utf-8\"?>");

			androidHttpTransport.call(SOAP_ACTION, envelope);
			SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn;
			result = Double.parseDouble(resultsRequestSOAP.getProperty("AddResult").toString());
		}
		while(false);
		return result;
	}

Не забываем обратить внимание на магический флаг envelope.dotNet – без него к .NET сервису подключиться не получится.
Также есть проблемы с подключением к WCF-сервисам. У меня так и не получилось вызвать метод из WCF-сервиса (судя по тикетам проекта ksoap2-android, у многих та же проблема, но говорят что все-таки как-то можно…)

Еще есть проблема с численными параметрами. У меня упорно не хотело сериализировать параметры типа double, пришлось передавать их в виде строки (судя по примерам, все так делаю, видимо так и надо).

Скачать исходный код примера.

Еще интересные посты о программировании для мобильных устройств:

No Comments

Make A Comment

No comments yet.

Comments RSS Feed   TrackBack URL

Leave a comment

Please leave these two fields as-is:

top