Всем время от времени хочется странного. Вот мне тоже захотелось такого. А именно – подружить 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, пришлось передавать их в виде строки (судя по примерам, все так делаю, видимо так и надо).

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

Previous ArticleNext Article
Технический директор IT-Dimension, компании-разработчика кросс-платформенного программного обеспечения

Leave a Reply

Your email address will not be published. Required fields are marked *

A.

Android SDK 1.5 Released

Ну и вот. Google наконец-то выпустила Android SDK 1.5

В этой версии:

  • Поддержка нескольких версий платформы Android (1.1 и 1.5)
  • Новая штука – Android Virtual Devices (AVD). AVD – это набор опций эмулятора, который позволяет лучше эмулировать особенности реальных устройств.
  • Поддержка add-on’ов (дополнительных библиотек).
  • Новая версия плагина для разработки в Eclipse
  • Улучшена поддержка JUnit
  • Улучшена работа с профилировщиком приложений
  • Улучшено управление локализацией приложений

В этой версии SDK программный инструментарий для работы с картами исключен из образа системы и доступен как внешняя библиотека (add-on). Скачать можно здесь.

Полный список нововведений с пояснениями.

С.

Собираем wxWinCE, C++ библиотеку для разработки GUI приложений под PocketPC!

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

Сегодня мы поговорим о том, как собрать библиотеку wxWidgets, а точнее ее порт wxWinCE, который используется для разработки приложений, работающих под управлением Windows Mobile и значительно упрощает процесс разработки GUI-приложений для карманных компьютеров и смартфонов под упралвением этой ОС. Для того чтобы собрать wxWinCE мы будем использовать Visual Studio 2008.

Итак, для начала нам необходимо загрузить исходный код wxWidgets с официального сайта. Сделать это можно здесь. На странице доступны различные версии дистрибутива wxWidgets, а также пакеты для различных ОС. На данный момент последней версией является 2.8.8. Лучше всего будет загрузить пакет wxALL (пакет, содержащий исходный код wxWidgets для всех поддерживаемых платформ и операционных систем).

После того как исходный код библиотеки загружен, распаковываем его и переходим в папку wxWidgets-2.8.8/build/wince. Здесь находятся файлы проектов для wxWinCE.

Открываем файл проекта wx_mono.vcp. При открытии Visual Studio предложит преобразовать файл проекта к новому формату.

Теперь, для того чтобы собрать библиотеку, нам необходимо сделать несколько подготовительных действий. Все дополнительные действия по настройке проекта необходимо проделать для каждой платформы, под которую будет собрана wxWidgets, потому что в противном случае собрать приложение с неправильно настроенной библиотекой будет невозможно.

В этом посте для примера будет использована платформа Pocket PC 2003 и Windows Mobile 6 Professional. Почему выбраны именно эти платформы? Pocket PC 2003 выбрана как самая старая. Приложения, собранные под эту платформу будут также работать под управлением более поздних версий Windows Mobile. Windows Mobile 6 Professional выбрана как самая новая.

Итак, открываем окно свойств проекта и переходим в раздел Configuration Properties -> General. В этом разделе в свойстве Output Directory устанавливаем значения:

  • Для платформы Pocket PC 2003 – “..\..\lib\evc_armv4_lib”
  • Для платформы Windows Mobile 6 Professional – “..\..\lib\evc_armv4t_lib”

Сделать это нужно для обеих конфигураций, Debug и Release.

Переходим в раздел Librarian -> General и в свойстве Output File устанавливаем значение $(OutDir)\$(ProjectName).lib для Release конфигурации и $(OutDir)\$(ProjectName)d.lib для Debug конфигурации.

Для платформы Windows Mobile 6 Professional переходим в раздел C/C++ -> Advanced и в свойстве Compile for Architecture устанавливаем значение ARM4T (QRarch4t).

Идем в раздел C/C++ -> Code Generation и в свойстве Enable C++ Exceptions устанавливаем значение No. Необходимо помнить, что сделать это нужно для обеих конфигураций и для обеих платформ.

Пытаемся собрать библиотеку, жмем Build. И что мы видим? Ошибки!!! Первое с чем прийдется столкнуться, это ошибка вида

—— Build started: Project: wx_mono, Configuration: Debug Pocket PC 2003 (ARMV4) ——
Creating ..\..\lib\evc_armv4_lib\winced\wx\msw\rcdefs.h
“clarm.exe” не является внутренней или внешней
командой, исполняемой программой или пакетным файлом.
Project : error PRJ0019: A tool returned an error code from “Creating ..\..\lib\evc_armv4_lib\winced\wx\msw\rcdefs.h”
Build log was saved at “file://e:\wxWidgets-2.8.8\build\wince\Pocket PC 2003 (ARMV4)\Debug\BuildLog.htm”
wx_mono – 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Лечится она просто, необходимо повторно запустить сборку проекта.

Смотрим дальше, ошибка вида

e:\wxWidgets-2.8.8\include\wx/aui/floatpane.h(33) : error C2504: ‘wxMiniFrame’ : base class undefined
..\..\src\aui\framemanager.cpp(2453) : error C2039: ‘SetTransparent’ : is not a member of ‘wxAuiFloatingFrame’
e:\wxWidgets-2.8.8\include\wx/aui/floatpane.h(32) : see declaration of ‘wxAuiFloatingFrame’

Лечится она тоже довольно просто, открываем файл floatpane.h и меняем декларацию макроса wxAuiFloatingFrameBaseClass чтобы оно выглядел так:

#if defined( __WXMSW__ ) || defined( __WXMAC__ ) ||  defined( __WXGTK__ )
#include "wx/minifram.h"
#define wxAuiFloatingFrameBaseClass wxFrame
#else
#define wxAuiFloatingFrameBaseClass wxFrame
#endif

Следующее, ошибка вида

..\..\src\msw\window.cpp(5965) : error C3861: ‘VkKeyScan’: identifier not found

лечится добавлением функции-заглушки


unsigned int VkKeyScan(int)
{
return 0;
}

Хотелось бы отметить что в версии 2.8.7 библиотеки этой ошибки нет и если уж совсем не хочется что-то править в исходниках wxWidgets, то можно воспользоваться версией 2.8.7.

Ну вот, теперь можно собирать библиотеку. Собираем Debug и Release конфигурацию для обеих платформ.

Дальше, для удобства использования wxWinCE в проектах, нам необходимо добавить переменную окружения WXWIN и присвоить ей в качестве значения путь папке с исходным кодом wxWidgets.

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