Статьи

Использование веб-сервисов с помощью kSOAP

В этом руководстве вы узнаете, как использовать веб-службы с помощью популярной библиотеки kSOAP в приложении Android. kSOAP — это авторитетная библиотека, которую любят разработчики, которым необходимо анализировать сообщения WSDL (язык определения веб-служб) и SOAP (протокол простого доступа к объектам).


Библиотека kSOAP — это элегантная, легкая и эффективная клиентская библиотека SOAP. Библиотека с открытым исходным кодом, проста в использовании и может избавить вас от хлопот, связанных с программированием собственного анализатора. Это одна из самых надежных библиотек SOAP, доступных в настоящее время, и она часто обновляется, что является хорошим знаком для любого проекта с открытым исходным кодом.

Часто рискованно интегрировать программное обеспечение с открытым исходным кодом (OSS) в проект, так как это может вызвать непредвиденные проблемы в будущем. Всегда ищите комментарии и отзывы других разработчиков, которые использовали библиотеку. Если проект не находится в стадии активной разработки, может быть, лучше поискать альтернативное решение.

Цель этого руководства — познакомить вас с библиотекой kSOAP. В демонстрационных целях мы будем использовать простой веб-сервис от W3Schools . Веб-сервис — это конвертер Фаренгейта в Цельсий . Веб-сервис принимает значение в градусах Фаренгейта и отвечает эквивалентным значением в градусах Цельсия. Мы рассмотрим пример шаг за шагом. В конце этого урока мы отобразим результат на устройстве пользователя.


Запустите новый проект Android и настройте его по своему усмотрению. Не стесняйтесь использовать вашу любимую IDE, но для этого урока я буду использовать IntelliJ IDEA .

В файле манифеста проекта необходимо указать, что приложению разрешено подключаться к Интернету. Мы также собираемся указать целевую версию SDK и минимальную версию SDK. Посмотрите на файл манифеста, показанный ниже.

1
2
<uses-sdk android:minSdkVersion=»7″ android:targetSdkVersion=»17″/>
<uses-permission android:name=»android.permission.INTERNET»/>

Всегда старайтесь использовать последний стабильный выпуск библиотеки или обновляйте библиотеку, которую вы используете в приложении, после выпуска основного обновления. Рекомендуется поддерживать зависимости проекта в актуальном состоянии по различным причинам, таким как безопасность и исправление ошибок. В этом руководстве мы будем использовать версию 3.1.1 библиотеки kSOAP, которую вы можете найти на странице загрузки проекта . После загрузки библиотеки kSOAP добавьте ее в папку libs вашего проекта.

Чтобы использовать библиотеку kSOAP в своем проекте, вам необходимо добавить ее в свой проект. Я покажу вам, как добавить его с помощью IntelliJ IDEA. Шаги могут немного отличаться, если вы используете другую IDE, но идея та же. В IntelliJ IDEA выберите « Структура проекта …» в меню « Файл» , откройте панель « Модули» , нажмите кнопку « плюс» в нижней части правой панели и выберите библиотеку. Перейдите в папку libs и выберите библиотеку kSOAP. Посмотрите на два изображения ниже для пояснения.



Библиотека kSOAP теперь должна отображаться как зависимость вашего проекта. Установите флажок рядом с библиотекой kSOAP, чтобы добавить ее в свой проект. Теперь, когда мы добавили библиотеку в наш проект, пришло время использовать ее. Если вы используете IntelliJ IDEA, ваш проект должен выглядеть примерно так, как показано ниже.



Использование библиотеки kSOAP для использования веб-службы включает в себя ряд шагов. Однако, прежде чем мы начнем изучать библиотеку kSOAP, полезно рассказать вам немного о веб-сервисе, который мы будем использовать.

Посетите веб- сайт веб-службы W3Schools, который мы будем использовать в этом руководстве. Вы увидите, что есть две операции, CelsiusToFahrenheit и FahrenheitToCelsius . Название каждой операции не требует пояснений. URL-адрес веб-службы — это базовый URL-адрес, который мы будем использовать для подключения к веб-службе.

Если вы выберете операцию на веб-сайте W3Schools , вам будет показан пример запроса, который ожидает веб-служба, а также ответ веб-службы. Взгляните на фрагмент кода ниже, который представляет собой пример запроса, который ожидает веб-служба. Обратите особое внимание на SOAPAction в фрагменте кода. Мы будем использовать его чуть позже в этом уроке.

1
2
3
4
5
6
7
POST /webservices/tempconvert.asmx HTTP/1.1
Host: www.w3schools.com
Content-Type: text/xml;
Content-Length: length
SOAPAction: «http://www.w3schools.com/webservices/FahrenheitToCelsius»
<!—?xml version=»1.0″ encoding=»utf-8″?—>
string

Следующий фрагмент кода показывает пример ответа веб-службы.

1
2
3
4
5
HTTP/1.1 200 OK
Content-Type: text/xml;
Content-Length: length
<!—?xml version=»1.0″ encoding=»utf-8″?—>
string

Первое, что нам нужно сделать, — это создать конверт SOAP с использованием класса org.ksoap2.serialization.SoapSerializationEnvelope ( org.ksoap2.serialization.SoapSerializationEnvelope ), который необходимо импортировать из библиотеки kSOAP. Взгляните на фрагмент кода ниже, в котором я инициализировал экземпляр класса SoapSerializationEnvelope .

1
SoapSerializationEnvelope envelope = getSoapSerializationEnvelope(request);

Метод getSoapSerializationEnvelope не определен в библиотеке kSOAP. Это вспомогательный метод, который я создал для облегчения работы с библиотекой kSOAP. Метод возвращает конверт SOAP, который нам нужен для остальной части примера. Посмотрите на реализацию getSoapSerializationEnvelope ниже.

1
2
3
4
5
6
7
8
9
private final SoapSerializationEnvelope getSoapSerializationEnvelope(SoapObject request) {
    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.dotNet = true;
    envelope.implicitTypes = true;
    envelope.setAddAdornments(false);
    envelope.setOutputSoapObject(request);
 
    return envelope;
}

Метод getSoapSerializationEnvelope принимает экземпляр SoapObject , который является запросом. Мы увидим, как создать запрос всего за несколько минут. При создании экземпляра класса SoapEnvelope версия SoapEnvelope устанавливается путем передачи в SoapEnvelope.VER11 , который сообщает библиотеке kSOAP, что мы будем использовать SOAP 1.1 . Мы устанавливаем для свойства dotNet конверта dotNet true поскольку веб-служба, которую мы будем использовать, работает на платформе Microsoft .NET.

1
envelope.dotNet = true;

Настало время настроить конверт SOAP, установив информацию о запросе. Начните с импорта класса SoapObject ( org.ksoap2.serialization.SoapObject ) и взгляните на фрагмент кода ниже, чтобы узнать, как настроить конверт. Мы начнем с создания экземпляра класса SoapObject , который требует двух параметров, пространства имен и имени метода . Вы можете добавить дополнительные свойства к запросу, используя метод addProperty как показано ниже. В нашем примере я использую addProperty для добавления значения в градусах Фаренгейта к запросу.

1
2
3
String methodname = «FahrenheitToCelsius»;
SoapObject request = new SoapObject(NAMESPACE, methodname);
request.addProperty(«Fahrenheit», fValue);

Вы можете быть удивлены, откуда исходит NAMESPACE . Это частная статическая строка, которая определена в другом месте приложения, как вы можете видеть ниже.

1
private static final String NAMESPACE = «http://www.w3schools.com/webservices/»;

Чтобы отправить запрос в веб-сервис, нам нужно создать запрос транспорта HTTP. Для этого мы будем использовать класс org.ksoap2.transport.HttpTransportSE ( org.ksoap2.transport.HttpTransportSE ). Посмотрите на пример ниже.

1
HttpTransportSE ht = getHttpTransportSE();

Как вы уже догадались, getHttpTransportSE — это еще один вспомогательный метод, который позволяет быстро создать транспортный объект HTTP. Это делает менее утомительным создание транспортного объекта HTTP каждый раз, когда вы выполняете вызов веб-службы. Посмотрите на его реализацию ниже. Чтобы создать экземпляр HttpTransportSE , нам нужен только базовый URL-адрес веб-службы, который представляет собой другую частную статическую строку, как вы можете видеть ниже.

1
2
3
4
5
6
private final HttpTransportSE getHttpTransportSE() {
    HttpTransportSE ht = new HttpTransportSE(Proxy.NO_PROXY,MAIN_REQUEST_URL,60000);
    ht.debug = true;
    ht.setXmlVersionTag(«<!—?xml version=\»1.0\» encoding= \»UTF-8\» ?—>»);
    return ht;
}
1
private static final String MAIN_REQUEST_URL = «http://www.w3schools.com/webservices/tempconvert.asmx»;

В getHttpTransportSE мы также настраиваем объект HttpTransportSE . Proxy.NO_PROXY в качестве первого аргумента конструктора, мы указываем, что прокси-сервер не используется для запроса. Третий аргумент конструктора устанавливает время ожидания сеанса в миллисекундах. Чтобы упростить отладку, мы также устанавливаем для свойства debug объекта значение true . Любые проблемы, которые всплывают, регистрируются в LogCat.

Пришло время отправить запрос SOAP на веб-сервис. Мы делаем это через HTTP, используя объекты транспорта и конверта, которые мы создали ранее. Транспортный объект HTTP имеет метод call , который используется для добавления действия SOAP и конверта, который мы создали ранее.

1
ht.call(SOAP_ACTION, envelope);

SOAP_ACTION — это еще одна закрытая статическая строка, как вы можете видеть ниже.

1
private static final String SOAP_ACTION = «http://www.w3schools.com/webservices/FahrenheitToCelsius»;

Когда веб-служба отправляет ответ, нам нужно обработать его и обработать любые ошибки, которые могли быть выданы. Затем мы можем отобразить данные для пользователя. Взгляните на фрагмент кода ниже, в котором мы извлекаем ответ из конверта ответа, используя метод getResponse .

1
SoapPrimitive resultsString = (SoapPrimitive)envelope.getResponse();

Я использую тип SoapPrimitive , но вы также можете использовать экземпляр SoapObject если ответ от веб-службы XML. Затем вы можете использовать экземпляр SoapObject чтобы получить значения ответов и сохранить их в массиве. Вызовите toString SoapPrimitive объекта SoapPrimitive чтобы преобразовать ответ в простую строку для использования в вашем приложении.

Взгляните на следующий фрагмент кода, в котором я реализовал метод getCelsiusConversion . Метод принимает строковую переменную в качестве единственного аргумента. Переменная добавляется как свойство в запрос SOAP, как мы видели ранее в этом руководстве. Переменная, потребляемая методом — это значение в градусах Фаренгейта. Это значение отправляется и обрабатывается веб-службой, и мы получаем ответ в градусах Цельсия.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public String getCelsiusConversion(String fValue) {
        String data = null;
        String methodname = «FahrenheitToCelsius»;
 
        SoapObject request = new SoapObject(NAMESPACE, methodname);
        request.addProperty(«Fahrenheit», fValue);
 
        SoapSerializationEnvelope envelope = getSoapSerializationEnvelope(request);
 
        HttpTransportSE ht = getHttpTransportSE();
        try {
            ht.call(SOAP_ACTION, envelope);
            testHttpResponse(ht);
            SoapPrimitive resultsString = (SoapPrimitive)envelope.getResponse();
 
            List COOKIE_HEADER = (List) ht.getServiceConnection().getResponseProperties();
 
            for (int i = 0; i < COOKIE_HEADER.size(); i++) {
                String key = COOKIE_HEADER.get(i).getKey();
                String value = COOKIE_HEADER.get(i).getValue();
 
                if (key != null && key.equalsIgnoreCase(«set-cookie»)) {
                    SoapRequests.SESSION_ID = value.trim();
                    Log.v(«SOAP RETURN», «Cookie :» + SoapRequests.SESSION_ID);
                    break;
                }
            }
            data = resultsString.toString();
 
        } catch (SocketTimeoutException t) {
            t.printStackTrace();
        } catch (IOException i) {
            i.printStackTrace();
        } catch (Exception q) {
            q.printStackTrace();
        }
   return data;
}

Я использую две строки в getCelsiusConversion , data и methodname . Переменная data будет возвращена методом после того, как веб-служба отправит ответ, в то время как methodname хранит имя операции веб-службы, на которую мы нацелены, и используется в экземпляре SoapObject .

Возможно, вы заметили цикл for в getCelsiusConversion , который не является частью шагов, которые мы обсуждали ранее. При работе с более сложными веб-сервисами важно отслеживать текущий сеанс. В приведенном ниже фрагменте я сохраняю сеанс и отслеживаю его каждый раз, когда звоню в веб-службу.

1
2
3
4
5
6
7
8
9
for (int i = 0; i < COOKIE_HEADER.size(); i++) {
    String key = COOKIE_HEADER.get(i).getKey();
    String value = COOKIE_HEADER.get(i).getValue();
    if (key != null && key.equalsIgnoreCase(«set-cookie»)) {
        SoapRequests.SESSION_ID = value.trim();
        Log.v(«SOAP RETURN», «Cookie :» + SoapRequests.SESSION_ID);
        break;
    }
}

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

Сначала нам нужно создать файл XML в папке макета проекта. Посмотрите на фрагмент кода ниже. Это простая иллюстрация пользовательского интерфейса, созданного в XML.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?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» />
<EditText
 android:layout_width=»200dp»
 android:layout_height=»wrap_content»
 android:layout_gravity=»center_horizontal»
 android:hint=»Fahrenheit»
 android:inputType=»number»
 android:id=»@+id/value_to_convert» />
 
<Button
 android:layout_width=»200dp»
 android:layout_height=»wrap_content»
 android:layout_gravity=»center_horizontal»
 android:text=»Convert to Celsius»
 android:id=»@+id/convert» />
 
<TextView
 android:layout_width=»fill_parent»
 android:layout_height=»wrap_content»
 android:gravity=»center_horizontal»
 android:textSize=»30dp»
 android:id=»@+id/answer» />
</LinearLayout>

Мы создаем три компонента, экземпляр EditText экземпляр Button и экземпляр TextView . Экземпляр EditText используется для ввода и захвата значения, которое мы намереваемся отправить веб-службе. Кнопка используется для запуска потока, который вызывает getCelsiusConversion а текстовое представление отображает ответ, который мы получаем от веб-службы.

Следующим шагом является создание экземпляра Activity для отображения макета, который мы только что создали. Взгляните на следующий фрагмент кода. Это не должно быть слишком удивительно, если вы разрабатывали приложения для Android раньше.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package com.example.KsoapExample;
 
import android.app.Activity;
import android.os.Bundle;
 
public class MyActivity extends Activity {
    /**
    * Called when the activity is first created.
    */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.example.KsoapExample;
 
import android.app.Activity;
import android.os.Bundle;
 
public class MyActivity extends Activity {
    private TextView txt;
    private String celsius;
    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        final EditText edt = (EditText)findViewById(R.id.value_to_convert);
        Button btn = (Button)findViewById(R.id.convert);
        txt = (TextView)findViewById(R.id.answer);
 
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (edt.length() > 0) {
                    getCelsius(edt.getText().toString());
                } else {
                    txt.setText(«Fahrenheit value can not be empty.»);
                }
            }
        });
    }
}

В onCreate мы устанавливаем слушателя на кнопку, btn . Мы также дважды проверяем, что значение вводится в поле ввода перед отправкой его в веб-службу. В слушателе нажатия кнопки значение, переданное getCelsius в строку, поскольку веб-служба ожидает строковое значение. Реализация getCelsius не сложна, как вы можете видеть ниже.

01
02
03
04
05
06
07
08
09
10
11
private final void getCelsius(final String toConvert) {
    new Thread(new Runnable() {
 
        @Override
        public void run() {
            SoapRequests ex = new SoapRequests();
            celsius = ex.getCelsiusConversion(toConvert);
            handler.sendEmptyMessage(0);
            }
    }).start();
}

В getCelsius создается новый поток, который запускает и создает экземпляр класса, который реализует getCelsiusConversion . Когда мы получаем ответ от веб-службы, мы отправляем сообщение обработчику, чтобы обновить пользовательский интерфейс, отображая значение в градусах Цельсия для пользователя.

01
02
03
04
05
06
07
08
09
10
11
12
13
public Handler handler = new Handler(new Handler.Callback() {
 
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
 
            case 0:
                txt.setText(celsius);
                break;
        }
        return false;
    }
});

В обработчике мы обновляем экземпляр TextView значением, полученным от веб-службы. Посмотрите на конечный результат ниже.



Теперь вы сможете добавить библиотеку kSOAP в проект и использовать ее для отправки запросов веб-службе, использующей протокол SOAP. Работа с библиотекой kSOAP станет легче с небольшой практикой, и поэтому я призываю вас попробовать веб-сервис преобразования Цельсия в Фаренгейт. Попробуйте пример приложения для Android, которое является частью руководства, для получения дополнительной помощи.