Опубликован: 22.12.2015 | Доступ: свободный | Студентов: 253 / 40 | Длительность: 14:40:00
Лекция 31:

Коммуникация по протоколу HTTP

< Лекция 30 || Лекция 31 || Лекция 32 >

Регистрация привилении

Коммуникация по протоколу HTTP используется для одновременной передачи большого объема данных. Это делает ее удобной для использования в мобильных приложениях. В этом разделе мы поговорим о том, что требуется для коммуникации и как загружать изображения с Интернета.

Создайте новый проект 'HttpRequest.' Добавьте привилегию http://tizen.org/privilege/internet

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<manifest xmlns="http://tizen.org/ns/packages" api-version="2.3" package="org.example.httprequest" version="1.0.0">
<profile name="mobile"/>
<ui-application appid="org.example.httprequest" exec="httprequest" multiple="false" nodisplay="false" taskmanage="true" type="capp">
<label>httprequest</label>
<icon>httprequest.png</icon>
</ui-application>
<privileges>
<privilege>http://tizen.org/privilege/internet</privilege>
</privileges>
</manifest>

Запрос данных текстовой коммуникации

В этом разделе мы поговорим о реализации способности принимать текст с веб-сервера. Откройте файл исходного кода и внесите в него следующие изменения

#include "httprequest.h"

#include <curl/curl.h>
typedef struct MemoryStruct {
char *memory;
size_t size;
} memoryStruct;

typedef struct appdata {
Evas_Object *win;
Evas_Object *conform;
//Evas_Object *label;
Evas_Object *entry;
Evas_Object *icon;
memoryStruct ms;
} appdata_s;

Для коммуникации по протоколу HTTP используется библиотека CURL.

curl/curl.h — это заголовочный файл библиотеки CURL.

MemoryStruct — это структура в которой хранятся данные, полученные в результате коммуникации.

Icon — это объект Evas Image.

Мы реализуем возможность соединения с сервером и получение текстовых данных. Для этого нам потребуется добавить три функции выше create_base_gui().

static size_t
write_memory_cb(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
memoryStruct *mem = (memoryStruct *)userp;
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if(mem->memory == NULL) {
/* out of memory! */
dlog_print(DLOG_INFO, "tag", "not enough memory (realloc returned NULL)");
return 0;
}
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
void
get_http_data(const char* url, memoryStruct *data)
{
CURL *curl_handle;
CURLcode res;
data->memory = malloc(1); /* will be grown as needed by the realloc above */
data->size = 0;
/* no data at this point */
curl_global_init(CURL_GLOBAL_ALL);
/* init the curl session */
curl_handle = curl_easy_init();
/* specify URL to get */
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
/* send all data to this function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_memory_cb);
/* we pass our 'chunk' struct to the callback function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)data);
/* some servers don't like requests that are made without a user-agent
field, so we provide one */
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
/* get it! */
res = curl_easy_perform(curl_handle);
/* cleanup curl stuff */
curl_easy_cleanup(curl_handle);
/* we're done with libcurl, so clean it up */
curl_global_cleanup();
}
static void
btn_download_text(void *data, Evas_Object *obj, void *event_info)
{
appdata_s *ad = data;
char url[100]={0,};
sprintf(url, "http://api.openweathermap.org/data/2.5/weather?lat=37.498&lon=127.027&units=metric");
get_http_data(url, &ad->ms);
elm_object_text_set(ad->label, ad->ms.memory);
free( ad->ms.memory);
}

write_memory_cb() - это функция события, которая принимает ответы от сервера. Ее параметры следующие: контент, блок байтов, размер памяти и данные пользователя.

Вы можете рассчитать общий объем памяти за счет умножения второго параметра а третий параметр. Блок байтов обычно равен 1.

Следующий код связывает память со свойством memory структуры memoryStruct, использующимся для функции realloc() и копирует данные с помощью функции memcpy().

Затем он добавляет размер памяти к свойству size структуры memoryStruct и заменяет конец данных нс 0 на метку завершения.

get_http_data() - это функция, которая пытается установить коммуникацию с сервером.

curl_global_init(long flags) - это API, который инициализирует библиотеку CURL. Для приложений, использующих CURL, этот API должен запускаться один раз в начале.

curl_easy_init(void) - это API, который создает объект CURL.

curl_easy_setopt(CURL *curl, CURLoption option, ...) - это API, который определяет опции для объекта CURL. Тип этих опции могут быть следующими:

  • CURLOPT_URL: определяет URL -адрес.
  • CURLOPT_WRITEFUNCTION: определяет вызывающую функцию, которая получает результаты коммуникации.
  • CURLOPT_WRITEDATA: определяет пользовательские данные.
  • CURLOPT_USERAGENT: определяет пользовательский агент.

curl_easy_perform(CURL *curl) — это API, который запускает коммуникацию с сервером.

curl_easy_cleanup(CURL *curl) - это API, который удаляет данные CURL.

curl_global_cleanup(void) — это API, который удаляет полные данные библиотеки CURL. После того, как CURL была использована, этот API должен быть вызван по меньшей мере раз перед закрытием приложения.

btn_download_text() - это функция, которая при нажатии на кнопку получает текстовые данные с сервера и отображает результаты в метке.

Запросим была ли передана информация о некотором месте с координатами 37.498 северной широты и 127.027 восточной долготы. Мы создадим кнопку, при нажатии на которую будут приниматься данные с сервера прогноза погоды. Добавьте код в конец функции create_base_gui() .

/* Conformant */
ad->conform = elm_conformant_add(ad->win);
elm_win_indicator_mode_set(ad->win, ELM_WIN_INDICATOR_SHOW);
elm_win_indicator_opacity_set(ad->win, ELM_WIN_INDICATOR_OPAQUE);
evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_win_resize_object_add(ad->win, ad->conform);
evas_object_show(ad->conform);

/* Vertical box */
Evas_Object *vbox = elm_box_add(ad->win);
elm_box_padding_set(vbox, ELM_SCALE_SIZE(10), ELM_SCALE_SIZE(10));
elm_object_content_set(ad->conform, vbox);
evas_object_show(vbox);
{
/* Entry */
ad->entry = elm_entry_add(ad->conform);
evas_object_size_hint_weight_set(ad->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(ad->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_box_pack_end(vbox, ad->entry);
evas_object_show(ad->entry);
/* Button-1 */
Evas_Object *btn = elm_button_add(ad->conform);
elm_object_text_set(btn, "Text");
evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0);
evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, 0);
evas_object_smart_callback_add(btn, "clicked", btn_download_text, ad);
elm_box_pack_end(vbox, btn);
evas_object_show(btn);
}
/* Show window after base gui is set up */
evas_object_show(ad->win);
}

Мы создали элементы управления Box, Entry, и Button. Запустите пример. Нажмите на кнопку. На экране появятся данные о погоде в формате Json.

Загрузка изображений

В этом разделе мы реализуем возможность загружать изображения с сервера и отображать их в объекте Image. Добавьте код создания элементов управления Image и Button в функцию create_base_gui().

{
/* Entry */
ad->entry = elm_entry_add(ad->conform);
evas_object_size_hint_weight_set(ad->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(ad->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_box_pack_end(vbox, ad->entry);
evas_object_show(ad->entry);
/* Image */
ad->icon = elm_image_add(ad->conform);
evas_object_size_hint_weight_set(ad->icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
evas_object_size_hint_align_set(ad->icon, EVAS_HINT_FILL, EVAS_HINT_FILL);
elm_box_pack_end(vbox, ad->icon);
evas_object_show(ad->icon);
/* Button-1 */
Evas_Object *btn = elm_button_add(ad->conform);
elm_object_text_set(btn, "Text");
evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0);
evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, 0);
evas_object_smart_callback_add(btn, "clicked", btn_download_text, ad);
elm_box_pack_end(vbox, btn);
evas_object_show(btn);
/* Button-2 */
btn = elm_button_add(ad->conform);
elm_object_text_set(btn, "Image");
evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, 0);
evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, 0);
evas_object_smart_callback_add(btn, "clicked", btn_download_image, ad);
elm_box_pack_end(vbox, btn);
evas_object_show(btn);
}

Мы создали объект Image и сохранили его в переменной icon структуры appdata. Затем мы создали вторую кнопку и определили имя вызывающей функции как btn_download_image. В заключение, нам нужно создать функцию -обработчик нажатия кнопки. Добавьте новую функцию выше create_base_gui() function.

static void
btn_download_image(void *data, Evas_Object *obj, void *event_info)
{
appdata_s *ad = data;
char url[100]={0,};
sprintf(url, "https://www.tizen.org/sites/all/themes/tizen_theme/logo.png");
get_http_data(url, &ad->ms);
// update icon image.
if ( elm_image_memfile_set( ad->icon, ad->ms.memory , ad->ms.size, "png", 0) == EINA_FALSE)
{
dlog_print(DLOG_DEBUG, "tag", "%s : image setting error " , __func__);
}
free( ad->ms.memory);
}

elm_image_memfile_set(Evas_Object *obj, const void *img, size_t size, const char *format, const char *key) — это API, который вводит данные оригинального изображения в объект Evas Image. Его параметры следующие: объект Evas Image, image data, data size, и image type. Запустите пример. Убедитесь, что загруженная с Интернета картинка отображается на экране.


< Лекция 30 || Лекция 31 || Лекция 32 >