Коммуникация по протоколу HTTP
Регистрация привилении
Коммуникация по протоколу 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 — это структура в которой хранятся данные, полученные в результате коммуникации.
Мы реализуем возможность соединения с сервером и получение текстовых данных. Для этого нам потребуется добавить три функции выше 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. Запустите пример. Убедитесь, что загруженная с Интернета картинка отображается на экране.