레이블이 tizen인 게시물을 표시합니다. 모든 게시물 표시
레이블이 tizen인 게시물을 표시합니다. 모든 게시물 표시

2020년 1월 22일 수요일

Galaxy Watch용 Tizen xamarin app에서 Entry에 의한 화면 깨짐 발생 시

Galaxy Watch app을 Xamarin.forms를 이용해서 C#으로 만들 수 있음.
https://samsung.github.io/Tizen.CircularUI/guide/Quickstart.html
기존에는 어려운 EFL 기반 app이나 web app을 만들어야 했는데 이제는 C#으로도 개발할 수 있음.

암튼 Watch 용 app을 하나 만들어 보는 중에
입력을 위한 Page가 필요하여 Entry를 추가하게 되었음.

하지만 페이지에서 Entry를 선택하면 Virtual Keyboard가 떠서
Page layout 밀려 올라가 이상하게 보이는 현상이 발생했다.

관련하여 다른 옵션이 없는지 확인 중 Tizen에서 제공하는 CircularUI가 있고
그 중에 PopupEntry를 제공하는 것을 확인하였음.

https://samsung.github.io/Tizen.CircularUI/guide/PopupEntry.html

Popup Entry는 일반적으로 Galaxy Watch app에서 사용되는
전체화면을 가리는 popup으로 입력창과 키보드가 떠서
기존 Page layout에는 영향을 주지 않고 입력할 수 있게 해준다.





참고로 안드로이드에서는 다음과 같이 처리하고 있음.
https://www.milestre.nl/blog/blogitem/milestre-blog/2019/01/08/to-avoid-soft-keyboard-overlap

//To avoid soft keyboard statusbar overlap            Xamarin.Forms.Application.Current.On().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);

2016년 12월 2일 금요일

Tizen 기반 기기(Gear, Z)의 Tizen platform version 확인하는 방법


Tizen 기기에 올릴 app을 만들려면
Tizen Sutdio에서 Tizen 기기에 맞는 Tizen Platform을 선택해야 하는데 모호한 경우가 많음.
이때는 Tizen 기기의 아래 파일을 보면 되는데
가지고 있는 Gear S2를 확인해 보면 /etc/config/model-config.xml 의 값을 확인하는 것이 맞겠다.

Tizen Platform version을 확인할 수 있는 파일들

- cat /etc/tizen-release
- cat /etc/config/model-config.xml

근데 확인해 보면
tizen-release 파일과 model-config 파일의 내용이 좀 다른 것을 알 수 있는데
이유는 잘 모르겠고 결과적으로 model-config의 Tizen 2.3.1이 맞지 않는가 생각 됨.

$ sdb connect / $ sdb connect <무선 연결이라면 기기 IP adress>
$ sdb shell
sh-3.2$ cat /etc/tizen-release
Tizen release 2.3.0 (Magnolia)

sh-3.2$ cat /etc/config/model-config.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<model-config version="2.3.1" model="SM-R732">
        <platform>
                <key name="tizen.org/system/model_name" type="string">SM-R732</key>
                <key name="tizen.org/system/platform.name" type="string">Tizen</key>
                <key name="tizen.org/feature/platform.version" type="string">2.3.1.7</key>
                <key name="tizen.org/feature/platform.version.name" type="string">Tizen</key>
                <key name="tizen.org/system/platform.processor" type="string">Exynos 3250</key>
                <key name="tizen.org/system/platform.communication_processor" type="string">none</key>


참고로 model-config의 값들은 아래 API를 사용하여 획득할 수 있음


2016년 7월 13일 수요일

Gear S 기기에 Tizen App 설치 오류 해결 방법



Gear S (SM-R750) 에 Tizen app을 설치를 위해서는

- Tizen IDE에 2.3 wearable package로 빌드? 및 설치 해야 함.
- Gear S에는 web app 설치 만 가능 하다.
- config.xml에서 Required version을 2.3에서 2.2로 변경 해야 함



 : 프로젝트 내 config.xml 파일 열기 > Tizen tab 선택 > Required version 을 2.2로 수정

Tizen 디바이스의 platform 버전에 맞는 app을 설치해야 하며
Gear S2의 경우는 Tizen 2.3.1이고 Gear S의 경우는 Tizen 2.3인 것 같은데(2.2인가?),
암튼 해당 기기에 맞는 버전으로 빌드 후 설치 가능하다.


그리고 Tizen IDE에서 필요한 Tizen package가 없다면
Tizen SDK가 설치 된 폴더 내 update-manager 폴더내
( C:\tizen-sdk\update-manager,  ~/tizen-sdk/update-manager)
update-manager를 실행하여 원하는 package를 추가 설치 해야 함.


2016년 5월 11일 수요일

Tizen Gear S2에서 지역에 따른 date 출력 방법

Tizen Gear S2에서 locale에 따른 date를 출력하기 위해 찾아봄

i18n (Internationalization)
: https://ko.wikipedia.org/wiki/%EA%B5%AD%EC%A0%9C%ED%99%94%EC%99%80_%EC%A7%80%EC%97%AD%ED%99%94

Tizen i18n Tutorial & Guide
: https://developer.tizen.org/ko/development/api-tutorials/native-application/base/i18n#dates
 : https://developer.tizen.org/ko/development/guides/native-application/base/i18n?langredirect=1

Get System Settings for Current Locale, Time Zone
 : https://developer.tizen.org/ko/development/tutorials/native-application/system/system-settings
 : https://developer.tizen.org/ko/development/guides/native-application/system/system-settings?langredirect=1

Date, Time Display Guide by Time Zones
 : https://developer.tizen.org/ko/development/api-tutorials/web-application/tizen-features/system/time



<샘플코드>

#include <utils_i18n.h>
#include <system_settings.h>

bool print_loca_date()
{
i18n_udatepg_h pattern_generator = NULL;
char *locale;

if (SYSTEM_SETTINGS_ERROR_NONE != system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, &locale))
return false;
dlog_print(DLOG_INFO, LOG_TAG, "Current Locale Country : %s\n", locale);

i18n_udatepg_create(locale, &pattern_generator);
if (!pattern_generator)
return false;

i18n_uchar bestPattern[64] = {0,};
char bestPatternString[64] = {0,};
int bestPatternLength, len;
const char *custom_format = "EEE, MMM d, yyyy 'at' HH:mm:ss zzz";
i18n_uchar uch_custom_format[64];

i18n_ustring_copy_ua(uch_custom_format, custom_format);
len = i18n_ustring_get_length(uch_custom_format);
i18n_udatepg_get_best_pattern(pattern_generator, uch_custom_format, len, bestPattern, 64, &bestPatternLength);
i18n_ustring_copy_au_n(bestPatternString, bestPattern, 64);
dlog_print(DLOG_INFO, LOG_TAG, "BestPattern(char[]) : %s \n", bestPatternString);
i18n_udatepg_destroy(pattern_generator);

i18n_udate_format_h formatter_Current = NULL;
i18n_uchar formatted[64] = {0,};
char result[64] = {0,};
int formattedLength;
i18n_udate date;
char *timezone_Current;
i18n_uchar utf16_timezone_Current[64] = {0,};

if (SYSTEM_SETTINGS_ERROR_NONE != system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_TIMEZONE, &timezone_Current))
return false;

i18n_ustring_copy_ua_n(utf16_timezone_Current, timezone_Current, strlen(timezone_Current));
if (I18N_ERROR_NONE != i18n_udate_create(I18N_UDATE_PATTERN , I18N_UDATE_PATTERN , locale,
utf16_timezone_Current, -1, bestPattern, -1, &formatter_Current))
return false;

if (utf16_timezone_Current)
{
i18n_ucalendar_get_now(&date);
i18n_udate_format_date(formatter_Current, date, formatted, 64, NULL, &formattedLength);
i18n_ustring_copy_au_n(result, formatted, 64);
dlog_print(DLOG_INFO, LOG_TAG, "Current Date : %s\n",result);
}
i18n_udate_destroy(formatter_Current);
return true;
}

<결과>

Current Locale Country : en_US
BestPattern(char[]) : EEE, MMM d, yyyy, h:mm:ss a zzz
Current Date : Thu, May 12, 2016, 11:22:56 AM GMT+9

Current Locale Country : de_DE
BestPattern(char[]) : EEE, d. MMM yyyy HH:mm:ss zzz
Current Date : Do., 12. Mai 2016 11:23:33 GMT+9

Current Locale Country : ko_KR
BestPattern(char[]) : yyyy년 MMM d일 (EEE) a h시 m분 s초 zzz
Current Date : 2016년 5월 12일 (목) 오전 11시 24분 13초 GMT+9

Current Locale Country : zh_CN
BestPattern(char[]) : yyyy年M月d日EEE zzzah:mm:ss
Current Date : 2016年5月12日星期四 GMT+9AM11:24:48

Current Locale Country : ja_JP
BestPattern(char[]) : yyyy年M月d日(EEE) H:mm:ss zzz
Current Date : 2016年5月12日(木) 11:25:13 GMT+9

Current Locale Country : hi_IN
BestPattern(char[]) : EEE, d MMM yyyy h:mm:ss a zzz
Current Date : गुरु, 12 मई 2016 11:26:29 AM GMT+9

2016년 5월 6일 금요일

Tizen Native app 개발 시 crash information에서 crash point file, line number 확인 방법

Tizen Native App의 crash 발생 시
crash information을 통해 crash가 발생된 file과 위치(line number)를 확인하는 방법을 정리함.

Native app 개발 하다 보면 Crash를 자주 보게 되는데
그냥 log만 사용해서 확인하자니 빌드 및 실행, 로그 추가로 좀 비효율적임.

다른 디버깅 방법으로 crash 발생 시 생성되는 crash information 중  callstack과
linux에서 개발을 하여 shell을 사용할 수 있다면
간단하게 crash가 발생한 위치를 addr2line을 사용하여 파악할 수 있다.



[Crash information 획득]


Tizen SDK를 사용하고 단말(Gear S2)가 연결이 되어 있는 상태라면
Crash 발생 시 자동으로 SDK에서 call stack view(Window > Show View > Call Stack)를 통해서 보여주게 된다.

Call Stack View를 통해 Crash information, Call stack, Crash 발생 당시 Log를 확인 가능하며
아래 사진은 Sample app을 사용하여 crash를 발생 시킨 것이라 다소 call stack depth가 얕다.

그리고 call stack 내에 app의 binary(ex basicuiw)의 실행 내역이 포함되어 있어야 해당 실행 주소를 사용하여 위치를 확인할 수 있다.




Callstack Information (PID:32525)
Call Stack Count: 1
 0: create_base_gui + 0x1c9 (0x4155e13a) [/opt/usr/apps/org.example.basicuiw/bin/basicuiw] + 0x113a
End of Call Stack


Call Stack에서 basicuiw 앱의 create_base_gui 함수에서 발생되었고 주소는 0x113a임을 알 수 있다.
이를 addr2line을 사용하여 확인하려면 다음과 같이 실행한다.
* 다만 여기서 사용하는 앱 바이너리(basicuiw) crash가 발생된 bianry와 같아야 한다.
   만약 crash 발생 이후 다시 컴파일을 했다면 위치를 확인하기가 어렵다.

hhh@:~/workspace_tizen/BasicUIw/Debug$ pwd
/home/hhh/workspace_tizen/BasicUIw/Debug
hhh@:~/workspace_tizen/BasicUIw/Debug$ addr2line -C -f -e basicuiw 0x113a
create_base_gui
/home/hhh/workspace_tizen/BasicUIw/Debug/../src/basicuiw.c:71

Crash는 basicuiw.c의 71번 line에서 발생한 것을 확인하였고
해당 위치를 확인하면 다음과 같이 crash가 발생하도록 작성한 코드가 맞음을 알 수 있음.




참고로 crash information들은 다음의 위치들에 저장이 된다.
SDK가 설치된 host pc의 app project 내 crash-info 폴더(연결 중 crash가 발생했다면)나
단말내 /opt/usr/share/crash/report 에서 확인할 수 있다.



2016년 2월 4일 목요일

Tizen edc 파일 사용 시 참고사항.

Tizen app 개발 시 GUI를 작성하다보면 어쩔 수 없이 사용해야 하는게 EDJE이다.
EFL code로도 작성할 수 있지만 간단한 GUI 같은 것은 EDJE로 구성하는게
간편함이나 코드량에서 편한 것 같 다.

EDJE로 개발 하면서 몇가지 정리함.

EDC 파일 에러 확인 방법
: edc 파일 수정 후 바로 확인하고 싶을 때 Project Explorer내 project의 edc 파일에서 오른쪽 클릭 해서 Build Selected File(s) 실행.
. 되도록이면 수정 하고 바로 확인하는 것을 추천 간혹 project 컴파일 시 edc 파일이 제대로 compile 안되도 그냥 넘어가는 현상이 있음.
. enventor에서 확인하도 되던데 내 환경에서는 이거 잘 실행 안되더라..

EDJE Program block에서 inherit 사용 시 주의점
: https://developer.tizen.org/development/ui-practices/native-application/efl/themes/edje-data-collection-reference?langredirect=1#program1
: widget들의 state를 변경하거나 event를 처리할 때 program을 사용하고 특정 stete를 기준으로 새로운 상태를 만들 수 있는 것이 'inherit' 임.
하지만 사용하다 보니 특정 상황(default state가 아닌 다른 state를 inherit할 때)에서 program 내의 inherit이 state보다 먼저 명시 되면 edc 컴파일 시 컴파일러가 죽는다.
 그래서 inherit를 사용할 때 왠만하면 documentation 처럼 state보다 먼저 명시 하지 말고 state 명시 후 inherit를 명시하여 사용하길.

Color alpha값 설정 시
: EFL에서의 color의 alpha 값범위는 0-255 까지 이므로 주로 사용하는 alpha값의 범위인 0-100을 기준으로 하려면 color x x x (alpha값/100*255); 이렇게 사용하면 편함.


2015년 11월 1일 일요일

Tizen SDK 사용 시 사소한 문제점에 대한 해결 방법들 및 팁

Tizen SDK는 계속 업데이트 되므로 아래 내용이 최신 SDK와 맞지 않을 수 있습니다.
아래 링크를 꼭 참고하세요.
https://developer.tizen.org/fr/community/tip-tech/trouble-shooting-certification
 
- 빌드 및 실행 시 아래 에러가 발생하면 

"An internal error occurred during: "Launching xxxxx - Debug (12)". 
Unknown character property name {o} near index 5
res\po\.*?.po
     ^
> 단말내 앱을 지우고 다시 설치하고 시도.
> 만약 EDC 기반 app이라면 EDC 파일을 선택하여 개별 빌드 해보고 오류가 없는지 확인 필요.


- TPK 생성 시 Certificate 복사 실패 

> Linux Tizen SDK로 빌드한 프로젝트를 Window Tizen SDK에서 빌드하여 TPK 생성하는 경우이고 certificate를 복사할 수 없다는 에러가 뜬다면 프로젝트 폴더내 .sign 폴더를 삭제하고 다시 빌드 및 설치 하라.


- 빌드 시 elf 관련 에러 발생 시

> 빌드 시 단말이 선택 되어 있는지 확인하고 제대로 선택되어 있다면 target architecture를 확인하라. Project Properties > C/C++ Build > Tizen Settings > Platform > Architecture


- 빌드 후 단말로 설치 시 transfer 관련 error가 발생하면

> 혹시 개발용 안드로이드폰이 usb로 연결되어 있으면 빼고 다시 시도해보길.

- edc 파일 컴파일 시 이미지 못찾는다는 에러 나올 때

> 윈도우 SDK를 사용 중이라면 edc 파일에서 마우스 우클릭 > Properties > C/C++ Build >
   Settings > Tool Settings > EDC Resource Compiler > misc > Image Path 가
   image가 있는 폴더를 가리키는 지 확인하라.
   보통 res/images에 image들을 저장하고 사용할텐데
   windows SDK에서는 edje/images 를 가리키고 있음.

- native project에서 JSON parsing 해야 할 때

> cJSON 추천 ㅈㄹ 간편하다. http://sourceforge.net/projects/cjson/


- C++ std library header들을 못 찾는다고 나올 때 

> 혹시 c 구현부에서 에러가 나는 C++ 구현부의 header를 include하는 곳이 없는지 확인해라.
> 그래도 안되면 환경 문제일 가능성 농후..


- 단말에서 project 실행 시 temporary하게 install/uninstall을 못하는 경우

> 단말에 맞는 certificate을 받아서 등록하고 단말 대상을 permit 했는지 확인하라.
https://www.youtube.com/watch?v=Xy2B-nlnprg&feature=youtu.be&t=2m10s


- Tizen 2.3 기반 app을 Tizen 2.4 SDK에서 빌드할 경우 .project에 2.4용 설정들이 포함되어 다시 Tizen 2.3 SDK에서 빌드를 못할 수 있음.

> repository의 history를 보고 rollback하거나 2.3 project를 새로 생성해서 하나하나 옮긴다.

2015년 10월 8일 목요일

Gear S2 sdb 연결 및 app 설치를 위한 인증서(certificate) 설정

[Gear S2와 개발용 host와 연결]


Gear S2에 app을 설치하기 위해서는 USB port가 없는 관계로  
usb가 아닌 WiFi를 사용하여 Gear S2를 개발용 host(PC, Laptop)와 연결해야 한다.

                         Connect via Wi-Fi

간단히 말하면 Gear에서 debuggin 옵션을 켜고 Reboot 후
BT를 끄고 개발용 host가 연결되어 있는 WiFi망에 Gear를 연결하면 된다.

좀 더 자세한 절차를 기술하자면...

(Gear S2에서)
1. Settings > Gear Info > Debugging ON
2. Reboot
3. Turn Off Bluetooth
4. Turn On Wi-Fi
5. Connect Wireless Router
6. Check IP address in Settings > Wi-Fi networks > connected Wi-Fi detail information

(SDK에서)
7. Open Remote Device Manager
8. New > Name > IP > Add
9. Connect
(Gear S2에서 PC/Laptop 연결을 허용 후)
10. Disconnect > Connect


sdb connect를 사용해도 되고 SDK의 Connection Explorer 중
Remote Device Manager에서 IP를 등록하고 연결 가능함.

(Troubleshooting)

- 혹시나 linux에서 sdb를 직접 설치했다면 그것은 지워버리고 SDK/tools/sdb를 사용하라.

- 개발용 Host(PC/Laptop)은 Wireless Router에 유선(cable)으로 연결되어 있어야 안정적인 연결이 가능하다.

- 개발용 Host나 S2 모두 무선(Wireless)으로 연결되어 있으면 sdb와 연결이 주변 무선 환경에 따라 쉽지 않을 수 있다. 

- 될 때 까지 sdb connect를 시도하고 연결이 된다면 개발용 Host에서 ping을 S2의 IP로 계속 호출해주는 것도 연결을 계속 유지하기 위한 방법일 수 있음.

- sdb connect가 한번에 안될 수도 있다. 그럴 때는 BT가 꺼져있는지와 IP를 확인한 뒤 될 때 까지 시도


아래 samsung developer site에서 Gear 개발 관련된 내용을 찾을 수 있고
관련된내용으로 d.denadai님이 간략히 정리한 내용이다.


http://developer.samsung.com/forum/thread/connecting-gear-s2-with-tizen-ide-/201/285623?boardName=SDK&startId=zzzzz~&searchSubId=0000000032#post1

Developer d.denadai , 9350 Seed Oct 05, 2015 10:18 Post #1 4 Hi!

 To connect your Gear S2 to the IDE on the computer you need to use SDB over the network.
- Connect your Gear S2 to a phone, so it can retrieve the Wi-Fi credentials from the phone;
- Enable debugging in the watch (settings > about);
- Turn the Bluetooth off, so the watch will now try and connect to a Wi-Fi network;
- Connect your pc to the same network;
- Connect SDB via the terminal : sdb connect <IP of the watch>

The watch is now visible from your IDE so you can deploy your application.

Cheers,
Didier 



아래는 좀 더 자세하게 설명하고 있는 설명

Connecting Gear S2 using Wi-Fi
: http://developer.samsung.com/technical-doc/view.do?v=T000000251L


[App 설치를 위한 인증서 설정]


개발 중 Gear S2에 app을 설치하기 위해서는 단말에 맞는 인증서를 설치해야 함.

이제 SDK 설치할 때 옵션으로 설치 가능하다.


2015년 6월 24일 수요일

Android Webview, Gear 상에서의 GPS 개발 관련 정리

[Geolocation API 사용을 위한 Android Webview 설정]


Android Webview 내에서 Geolocation API를 사용하려면 아래와 같은 설정이 필요하다.

참고
http://stackoverflow.com/questions/5329662/android-webview-geolocation


1. Android app에서 location 관련 permission 명시

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />


2. Geolocation API 사용을 위한 Webview 설정

: JavaScript enable, Geolocation enable, Geolocation caching을 위한 DB path 설정
http://developer.android.com/reference/android/webkit/WebSettings.html

webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setGeolocationEnabled(true);
webView.getSettings().setGeolocationDatabasePath(Context.getFilesDir().getPath());


아래 HTML5 관련 설정들은 실제 Geolocation API에 영향을 주는지 확인은 안했지만
사용하는 webview에서 사용하고 있었던 것이라 혹시나 안된다면 아래 것도 추가를..

webView.getSettings().setDatabaseEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setAppCacheEnabled(true);


3. 위치 정보 접근 허용을 위한 알림 및 허용 처리

: 위치정보 접근 허용을 위한 WebChromeClient.onGeolocationPermissionsShowPrompt() 구현
http://developer.android.com/reference/android/webkit/WebChromeClient.html#onGeolocationPermissionsShowPrompt(java.lang.String, android.webkit.GeolocationPermissions.Callback)

아래 예제에서는 그냥 사용자에게 prompt를 보여주지 않고 자동으로 위치정보를 접근하게 한예제이니 사용자에게 알릴 필요가 있다면 여기서 알려야함.

webView.setWebChromeClient(new WebChromeClient() {
 public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
    callback.invoke(origin, true, false);
 }
});


위 방법들을 사용하면 Android webview 내에서 Geolocation API를 사용할 수 있다.


[Geolocation APIs - getCurrentPosition, watchPosition]

: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation/Using_geolocation

getCurrentPosition, watchPosition에 대한 설명이다.

둘다 위치 정보를 얻기 위해 hardware를 사용하므로 비동기적(asynchronous)으로 callback을 통해 결과를 전달하는 것은 동일하지만 getCurrentPosition은 일회적으로 현재 위치를 제공하는 것이고 watchPosition은 위치의 변화가 있을 경우 변경된 좌표를 제공한다는 것이 다른 점이다.
또한 아래 설명의 굵은 글씨들을 참고하면 watchPosition이 이전 좌표를 기반하여 별도의 기술을 사용하여 좀 더 정확한 좌표를 제공하려 하는 것 같다. 아마도 Android webview에서 database path를 설정하는 것도 이런 연유에서일 것으로 추측..
하지만 watchPosition은 위치 변화 뿐만아니라 좀 더 정확한 위치가 설정 되어도 알려줘서 모르겠지만 수신 받은 위치를 좀 걸러내야 할 필요성이 있는 것 같다. 특히 GPS + 네트워크 둘다 사용할 경우 종종 부정확한 위치가 전달 된다.

(발췌, MDN Using Geolocation )

Getting the current position

To obtain the user's current location, you can call the getCurrentPosition() method. This initiates an asynchronous request to detect the user's position, and queries the positioning hardware to get up-to-date information. When the position is determined, the defined callback function is executed. You can optionally provide a second callback function to be executed if an error occurs. A third, optional, parameter is an options object where you can set the maximum age of the position returned, the time to wait for a request, and if you want high accuracy for the position.


Watching the current position

If the position data changes (either by device movement or if more accurate geo information arrives), you can set up a callback function that is called with that updated position information. This is done using the watchPosition() function, which has the same input parameters as getCurrentPosition(). The callback function is called multiple times, allowing the browser to either update your location as you move, or provide a more accurate location as different techniques are used to geolocate you. The error callback function, which is optional just as it is for getCurrentPosition(), can be called repeatedly.


이와 비슷한 내용의 Answer와 예제 샘플은 다음과 같다.

watchPosition API 사용 샘플
watchPosition을 계속 실행하면 아무래도 GPS 관련 hardware를 계속 사용하게 되므로 일정시간 watchPosition을 사용하되 몇초 단위로 끊어서 사용하고 있음.
: http://stackoverflow.com/questions/8552186/how-to-get-html5-position-in-webview-updated-at-a-regular-interval-with-fine-ac


Platform, OS 별 Geolocation 사용 예제
: http://docs.phonegap.com/en/edge/cordova_geolocation_geolocation.md.html

HTML5 Geolocation API 표준 문서
: http://www.w3.org/TR/geolocation-API/#geolocation_interface

이것도 참고하시라...
: http://www.andygup.net/how-accurate-is-html5-geolocation-really-part-2-mobile-web/


[Gear에서의 GPS 사용]



- GPS feature를 제공하는 제품들은 Gear2 neo, GearS가 있는 것으로 알고 있지만
   Gear 2에서는 Geolocation API를 사용할 수 없다. (Tizen 2.3 기준)

 . 그래서 GPS 센서가 없는 모델들은 SAP(Samsung Accessory Protocol)을 사용해서 mobile의 GPS 좌표를 사용하더라..
 (http://www.codeproject.com/Articles/830305/Speedometer-for-Galaxy-Gear-Tizen-Based)


- GearS는 GPS 센서가 있지만 GPS 센서, 네트워크 위치를 사용해서 위치를 파악한다.
 . GPS 센서만 사용하고자 한다면 설정 > 연결 > GPS만 사용 에 체크

 . FakeGPS를 사용하여 GearS GPS app디버깅 방법
  : SIM 카드가 없는 상태에서 설정 > 연결 > GPS만 사용 체크 해제
    GearS와 연결된 mobile의 GPS 끄고 fake GPS로 GPS 좌표 설정
    다만 Gear GPS센서가 동작이 안되는 상태에서 가능하므로 실내에서 가능하다..


[T map OpenAPIs]



https://developers.skplanetx.com/apidoc/kor/tmap/

타 통신사에서는 그림의 떡같은 T map인 관계로 별로 좋아하지 않았지만
이번에 Geolocation 관련 API을 찾다 보니 감사하게도 Open API들을 제공하고 있었다.
제공되는 API들도 꽤나 다양해서 GPS app 개발 시 상당히 유용할 것으로 보인다.

REST API를 사용해서 몇개를 사용해 봤는데 아래 사항은 지켜야 정상 응답을 하더라.

- url에서 callback, gizAppId는 값이 없어도 파라미터로 존재해야 한다.

예를 들어 경로 안내 API를 사용하려면
: https://developers.skplanetx.com/apidoc/kor/t-map/course-guide/geojson/

https://apis.skplanetx.com/tmap/routes?version=1&bizAppId={bizAppId}&callback={callback}

위와 같은 URL을 사용해야 하는데 bizAppId와 callback은 optional 항목이다.
하지만 bizAppid와 callback을 생략하고 ?version=1 만 적으면 정상 응답이 오지 않더라.
?bizAppId=&callback=&version=1 이렇게 적어 호출하니 정상응답.


- content type 설정

REST API 호출(HTTP request시) content type을 "Content-Type: application/x-www-form-urlencoded"로 설정해야 해서 jquery의 $.ajax()를 사용 시 header param으로 명시해야 한다.

2015년 5월 13일 수요일

Tizen WebView 사용 방법 정리, 설정, page 관련 signal, navigation policy 관리

Tizen Native app 개발 중 WebView를 사용하다 답답해서 정리함.

Tizen에서 제공하는 webview는 ewebkit2 기반이라고 한다.
자세한 내용과 간단한 사용 방법은 아래 링크 참고

Hello ewebkit?
: http://bunhere.tistory.com/m/post/417

Tizen WebView tutorial
https://developer.tizen.org/documentation/tutorials/native-application/web

Tizen WebView API reference
https://developer.tizen.org/dev-guide/2.3.0/org.tizen.native.mobile.apireference/group__WEBVIEW.html


Tizen document를 봐도 간단히 page만 loading하는 수준으로만 설명 되어 있고
그리고 몇가지 생각 나는 것은

- Tizen 2.2 platform API 대비 API 수준이 퇴화 한 것 같다.
 : 하나의 예로 WebView -> Native Interface가 없어졌음.

- WebView 내 page의 디버깅할 방법이 없다.
 : console log를 확인할 방법이 없고 안드로이드 처럼 크롬 개발자 도구 연동도 못한다.

- Documentation이 부실하다.
 : 예로 API reference상의evas_object_smart_callback_add()를 사용해서 처리하는 signal에 대해서는  signal definition과 argument type만 나오고 어떻게 사용하는지는 알 수 없다.


암튼... 삽질 하면서 몇가지 알게 된 것과
일반적인 Tizen Webview 사용 방법을 정리함.


[User agent 설정, Javascritp enable, cookie 사용 설정]

이부분은 API reference에 나와 있어서 쉽게 사용할 수 있는 부분임.

// user agent 설정
ewk_view_user_agent_set(ewk_view, "사용하고 싶은 USER AGENT");
Ewk_Settings* settings = ewk_view_settings_get(ewk_view);
// javascritp 사용 설정
ewk_settings_javascript_enabled_set(settings, true);

// 모든 cookie 사용 설정
  if(NULL != ewk_view_context_get(ewk_view) &&
NULL != ewk_context_cookie_manager_get(ewk_view_context_get(ewk_view)))
{
ewk_cookie_manager_accept_policy_set(ewk_context_cookie_manager_get(ewk_view_context_get(ewk_view)), EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
}

근데.. webview 내에서 cookie를 설정할 때
webview 내의 web page에서 javascript로 cookie를 설정할 경우는 생성이 되지만
native에서 webview로 javascript execute로 cookie를 설정할 경우는 잘 안된다.

그리고 안드로이드는 platform 차원에서 cookie를 관리하는 cookie manager가 있지만
Tizen은 그런 것 없다. 만약 일반 브라우저에서 로그인 후 생성된 cookie를 동기화 해야할 경우가 있다면.... 방법을 모르겠다.


[JavaScript 실행]

Native에서 WebView 내 API를 호출할 수 있고 이는 Native에서 WebView로 전달할 것이 있을 때 유용함.

ewk_view_script_execute(ewk_view,"자바스크립트 코드", 
            "결과 전달 callback", "callback으로 전달할 user_data");

typedef void(*Ewk_View_Script_Execute_Cb )(Evas_Object *o, const char *result_value, void *user_data)

근데 재미 있는 것은 callback의 result_value가 항상 null로 넘어온다. 언젠가 수정 될듯.
(다른분께서 알려주신건데 result_value가 script에서 마지막의 변수나 return값을 가지는 함수의 결과값이 전달된다고 하니 참고..)


[Page 관련 signal]

page loading 관련, URL 변경 관련 처리를 할 수 있는 signal들을 아래와 같이 등록 가능 함.

evas_object_smart_callback_add(ewk_view, "url,changed", __on_url_changed, user_data);
evas_object_smart_callback_add(ewk_view, "load,started", __on_load_started, user_data);
evas_object_smart_callback_add(ewk_view, "load,finished", __on_load_finished, user_data);
evas_object_smart_callback_add(ewk_view, "load,error", __on_load_error, user_data);

아래와 같이 page 시작 시 signal을 등록하여 처리할 수 있음.
다만 WebView engine에서 loading은 이미 시작된 후 efl port에서 IPC를 전달 받아
callback이 실행되므로 시점 차이가 있을 수 있다.

void __on_load_started(void *user_data, Evas_Object *webview, void *event_info)
{
const char* url = ewk_view_url_get(webview);
DLOG("__on_load_started, URL = %s", url);

}

URL 변경 시 변경된 URL에 따라서 처리할 수 있음.
Hash값이 변경 되었을 경우에도 이 callback이 불리어 hash에 따라서
native에서 처리할 수 있다.

void __on_url_changed(void *user_data, Evas_Object *webview, void *event_info)
{
appdata_s *ad = (appdata_s *)user_data;
const char* url = ewk_view_url_get(webview);

DLOG("__on_url_changed, URL = %s", url);

// Do something for the changed URL.
}

이것을 활용하면 JavaScript -> Native 코드 호출이 가능하다.
JavsScript에서 hash 값을 변경하여 url 뒤에 필요한 명령을 붙이고
Native에서 __on_url_changed event callback 내에서 url의 hash값을 보고
native 코드를 처리하면 된다.


[WebView page navigation policy]

특정 domain내의 page만 webview를 통해서 보여주고 싶을 경우
아래와 같이 signal을 등록해서 처리해야 한다.

evas_object_smart_callback_add(ewk_view, "policy,navigation,decide", __on_policy_navigation, ad);

callback 내에서 이동하려는 url을 ewk_policy_decison_url_get()으로 확인한 뒤
허용되는 domain 내의 page이면 ewk_policy_decision_use()로 이동 허용
아니면 ewk_policy_decision_ignore()로 이동 취소를 하면 됨.


void __on_policy_navigation(void *user_data, Evas_Object *webview, void *event_info)
{
Ewk_Policy_Decision* decision = (Ewk_Policy_Decision*)event_info;

string _loading_url((char*)ewk_policy_decision_url_get(decision));
string _current_url(ewk_view_url_get(webview));

// 허용되는 SITE_DOMAIN 인지 확인
if(0  == _loading_url.compare(0, strlen(SITE_DOMAIN), SITE_DOMAIN) )
{
ewk_policy_decision_use(decision);
return;
}

// 허용되지 않는 URL
ewk_policy_decision_ignore(decision);
}


2015년 5월 12일 화요일

Tizen Wearable 기기에 App 설치를 위한 Certificate 등록

Tizen SDK 2.3 Rev2를 설치하고
Wearable 기기에 앱을 설치하기 위해 Certificate을 등록하기 위해 방법을 찾아봤으나
정작 여러 포스팅이나 비디오에서 보이는 Certificate Request 아이콘이 SDK내에서 보이지 않는다.

Tizen SDK에서 Certificate 등록을 위해 SDK 내 아이콘을 선택하는 장면
https://youtu.be/Xy2B-nlnprg?t=2m10s


몇번의 SDK 재설치와 검색으로 찾아낸 정보로는
Certification을 위한 별도의 SDK가 존재해서 이것을 별도로 설치해줘야 한다.

Tizen Extension SDK for Certificate 다운로드
: http://developer.samsung.com/samsung-z#none

Tizen Extension SDK for Certificate 설치 방법
http://developer.samsung.com/technical-doc/view.do?v=T000000198
: http://seoz.egloos.com/4066593


이후 부터는 위 유투브 링크(https://youtu.be/Xy2B-nlnprg?t=2m10s)를 참고하여 설치하면 된다.

2014년 10월 21일 화요일

New native API in Tizen 2.3 Beta

Tizen 2.3 Beta 부터
기존 Native Framework layer에서 제공하던 OSP API(C++)들이 제거되고
Core layer의 C API들을 바로 사용하게 되었음. (하단 그림 참고)

https://www.mail-archive.com/general@lists.tizen.org/msg02334.html


기존 OSP API 쓰던 사람들은 멘붕일듯....

Tizen architecture

2014년 5월 22일 목요일

Tizen keypad에 ExpandableEditArea가 가려지지 않게 하는 방법

아래 내용은 Tizen 2.2 기반이라 상위 버전에서는 별 의미 없는 내용입니다.
---------------------------------------------------------------------------
Android 같은 경우 manifest에서 activity에 대해서 adjustPan, adjustResize 같은 option이 있어 자동으로 해결해 주지만 tizen의 form에서는 그렇지 않은것 같다. (아직 자동으로 form을 re-size 하게 하는 방법을 찾지 못함.)

keyboard의 event를 받아서 edit control를 수동으로 옮겨주는 방법을 사용해야 함.

: https://developer.tizen.org/dev-guide/2.2.1/org.tizen.native.appprogramming/html/tutorials/ui_tutorial/using_overlay_keypad_without_scroll.htm

Figure: Partially obscured edit field

위 방법으로는 화면상에서 virtual keypad가 표시되면 keypad의 height를 알아내서 입력하는 control(Edit control들)의 위치를 변경하는 방법이다.
즉 form 자체가 re-size되는게 아니라 keypad가 표시되면 keypad에 edit control이 가려지지 않도록 위치를 조정하는 방법임.

하다보니 좀 이상한게 있었는데
채팅창 처럼 입력 후 button을 클릭해야 한다면 해당 button도 keypad에 가려지지 않도록 위치도 조정을 해야 했었다. 하지만 직접 해보니 keypad생성 시 edit control과 함께 위치를 조정했지만 button이 클릭되지 않는 현상이 발생 ㅜㅜ 그래서 그냥 edit control만 keypad에 가려지지 않도록 하고 입력 후 back key를 눌러 keypad를 사라지게 한뒤 button 클릭 하게 하였음.


[ExpandableEditArea]

Expandable edit area

EditArea를 입력창으로 썼었는데 입력 시 전체화면에서 입력 하도록 전환이 되어 찾은 control임. 전체화면 입력을 사용하지 않고 입력창의 line같은 세부 설정이 가능함.

: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/ui/implementing_exp_editarea.htm

: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Ui_1_1Controls_1_1ExpandableEditArea.html

2014년 5월 14일 수요일

Tizen native app 개발 시 nine patched png 처리 이슈

아래 내용은 Tizen 2.2 기반이라 상위 버전에서는 별 의미 없는 내용입니다.
--------------------------------------------------------------------------- nine patch 적용된 png 파일을 사용하다보니
bitmap을 읽어오는 API에 따라서 nine patch image로 인식이 되지 않을 수 있어서 정리함.
(내가 방법을 모를지도..)

아래는 tizen 내부 저장소에서 그림을 읽어오는 sample code

result
MainForm::OnDraw(void)
{

// App resource(res/screen-density-xhigh)에서 나인패치 이미지 가져오는 예
// 하지만 이렇게 가져온 bitmap은 nine patch 로 인식 안됨 .
// false == pBitmap->IsNinePatchedBitmap()
// canvas->DrawNinePatchedBitmap() 시 에러메세지 발생

Bitmap* pBitmap = pAppResource->GetBitmapN(L"ninepatch.9.png");

// 아래는 App 영역내 data 폴더에 저장된 나인패치 이미지를 가져오는 예
// 이때는 정상적으로 인식됨.

Image image;
Bitmap* pBitmap = null;

image.Construct();
String filePath = App::GetInstance()->GetAppRootPath() + L"data/ninepatch.9.png";
pBitmap = image.DecodeN(filePath, BITMAP_PIXEL_FORMAT_ARGB8888, 100, 100);


Canvas* canvas = this->GetCanvasN(rect);
if (canvas != null)
{

r = canvas->DrawNinePatchedBitmap(Rectangle(0,0,100,100), *pBitmap);
AppLog("%d", r);

delete canvas;
}

Form::OnDraw();
}

2014년 5월 8일 목요일

Tizen app control

아래 내용은 Tizen 2.2 기반이라 상위 버전에서는 별 의미 없는 내용입니다.
--------------------------------------------------------------------------- Android intent와 유사하게 Tizen에서 다른 app을 실행하거나
처리결과를 받을 수 있도록 한 방법

app id나 app에 등록된 operation을 지정해서 실행 할 수 있음.
실행되는 app에서는 실행되고 있지 않을 경우 실행되면서 event를 받거나
실행중이면 바로 받게 된다.

: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/app/app_controls.htm



AppControl class

: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1App_1_1AppControl.html


[App 등록]
타 app이 사용할 실행을위한 operation을 등록하는 방법

: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/app/exporting_appcontrol_functionality.htm

Application manifest에서
<Apps> -> <UiApp>  -> <AppControls> -> <AppControl> -> <Operation> 을 등록
<AppControls>
   <AppControl>
      <Operation>http://tizen.org/appcontrol/operation/view</Operation>
      <Uri>custom</Uri>
   </AppControl>
   <AppControl>
      <Operation>http://tizen.org/appcontrol/operation/view</Operation>
      <MimeType>image/jpeg</MimeType>
   </AppControl>
</AppControls>

event listener 등록

: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/app/handling_appcontrol_request.htm



Tizen::App::IAppControlProviderEventListener  구현 후 OnAppInitializing()에서 등록

https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1App_1_1IAppControlProviderEventListener.html

* app이 실행될 때 마다 OnAppControlRequestReceived()가 계속 호출 된다. 호출 시 전달되는 argument들의 null check로 처리 해야 함.
* 위 그림에서 나와 있듯이 OnAppControlRequestReceived는 실행 시 app이 initialize되는 중에 실행 중에 호출 될 수 있음.
 . 시작 시 UiApp을 상속받은 class에서 event가 발생한다면 data를 저장해 두었다가 나중에 Form에서 처리하게 하던가 아니면 실행중이라면 바로 listener에서 처리하게 해야 할듯 하다.



[app 호출]

app ID로 launch 하는 방법
: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1App_1_1AppManager.html#ab0bb90797d2d13d718929acbb794eb26


* AppManager::FindAppControlN으로 하려고 했는데 appid로 application을 찾지 못하는 현상이 발생한다.. 뭐가 잘못이지?


operation id로 find and start 하는 방법

: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1App_1_1AppControl.html

    using namespace Tizen::App;

    void
    MyAppClass::AppControlDialSample(void)
    {

        String telUri = L"tel:12345678900";

        AppControl* pAc = AppManager::FindAppControlN(L"tizen.phone", L"http://tizen.org/appcontrol/operation/dial");
        if(pAc) 
        {
            pAc->Start(&telUri, null, null, null);
            delete pAc;
        }
    }


: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/app/delivering_launch_arguments.htm

FindAndStart (const Tizen::Base::String &operationId, const Tizen::Base::String *pUriPattern, const Tizen::Base::String *pDataType, const Tizen::Base::String*pCategory, const Tizen::Base::Collection::IMap *pExtraData, IAppControlResponseListener *pListener)



// Sharing single content
String fileUri = L"file:///opt/usr/media/Images/share.jpg";
AppControl::FindAndStart(L"http://tizen.org/appcontrol/operation/share", &fileUri, null, null, null, null);

AppControl status나 호출된 app으로 부터 response를 받고 싶다면 IAppControlResponseListener 를 상속하여 마지막 인자로 전달.


OnAppControlStartResponseReceived 는 AppControl이 시도되었을 시점, result 인자로 제대로 실행되었는지 아닌지 확인이 필요하다.
OnAppControlCompleteResponseReceived 는 AppControl로 실행된 app이 종료되고 난 뒤 시점에 호출된다. 시점을 자세히 말하면 GUI상으로 다시 app이 보여지고 좀 있다가 호출되어 이 함수가 호출되고 호출한 app이 실행된다고 보면 안될것 같고 호출한 app은 그냥 동작하고 result에 따른 처리는 asynchrnous하게 실행하도록 해야 할 것 같다.



2014년 5월 2일 금요일

Tizen Collections 중 ArrayList, LinkedList (native)

Tizen API를 사용하다보면
STL container 대신 tizen collection들을 사용해야 할 경우가 있어 정리함.

: https://developer.tizen.org/dev-guide/2.2.1/org.tizen.native.apireference/namespaceTizen_1_1Base_1_1Collection.html

https://developer.tizen.org/dev-guide/2.2.1/org.tizen.native.appprogramming/html/guide/base/collection_namespace.htm

 

일반적인 std::array, std::list를 대체할 Tizen의 자료구조이며 아래 나오는 제약사항을 숙지하고 구현해야 함. stl을 사용하다 tizen api들을 사용할 경우 다소 생소한 부분들이 있음.

ArrayList and LinkedList

https://developer.tizen.org/dev-guide/2.2.1/org.tizen.native.appprogramming/html/guide/base/arraylist_linkedlist.htm

제약사항

  • They override the IList methods to implement their own adding, removing, inserting, and writing mechanisms.
  • Indexes in them are zero-based.
  • They can be traversed using a Tizen::Base::Collection::IEnumerator interface.
  • They allow duplication of values, but do not accept null references.
  • They do not copy the values, but just keep the pointers to the values.
  • The RemoveAll() method is called internally by a destructor. Depending on the element deleter, the RemoveAll() method destroys all elements. You do not have to call the RemoveAll() method to deallocate all elements at the end.

위 제약사항에서 유의해야 하는 것은
IEnumerator interface를 사용해서 탐색하며
value가 아닌 pointer를 저장해야 하며
destructor에서 저장된 primitive value들을 알아서 deallocate함.

자세한 사용 방법은 위 링크에 포함된 예제를 보면 OK..

 #include <FBase.h>

    using namespace Tizen::Base;
    using namespace Tizen::Base::Collection;

    void
    MyClass::ArrayListTSample(void)
    {
        ArrayListT< int > list;

        list.Construct();

        int int1 = 1;
        int int2 = 2;
        int int3 = 3;
        int int4 = 4;

        list.Add(int1);     // 1
        list.Add(int2);     // 1,2
        list.Add(int3);     // 1,2,3

        int temp;
        for (int i = 0; i < list.GetCount(); i++)
        {
            list.GetAt(i, temp);
        }

        list.InsertAt(int4, 1);     // 1,4,2,3

        ComparerT< int >* pIntComparer = new ComparerT<int>();
        list.Sort(*pIntComparer);   // 1,2,3,4

        delete pIntComparer;

        list.Remove(int3);          // 1,2,4

        list.RemoveAt(0);           // 2,4

        // Uses an enumerator to access elements in the list
        IEnumeratorT< int >* pEnum = list.GetEnumeratorN();
        while (pEnum->MoveNext() == E_SUCCESS)
        {
            pEnum->GetCurrent(temp);
        }

        delete pEnum;
    }

위는 일반적인 primitive 자료형을 위한 자료구조라고 보면 될 듯하며 user-defined object를 처리하기 위해서는 다음 template base data structure를 사용 해야한다.

 Tizen::Base::Collection::ArrayListT<Type>
: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Base_1_1Collection_1_1ArrayListT.html


Tizen::Base::Collection::LinkedListT<Type>
https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Base_1_1Collection_1_1LinkedListT.html


위 페이지의 후반에서 설명하고 있다 시피 아래 Template based List들을 사용하려면 저장되는 object들은 대입, sort를 위한 비교 등에 필요한 operator들( =, ==, !=, <, >)을 구현해야 한다.

The Tizen::Base::Collection::ArrayListT<Type> and Tizen::Base::Collection::LinkedListT<Type> classes represent a template-based collection of objects that can be individually accessed by index, and behave similarly as the object-based class versions. These classes allow duplicate elements. Several methods in these classes need operators of the type assignment (=), equivalent (==), and not equivalent (!=). Furthermore, to use the Sort() method, relational operators (<>) or a comparer must be provided.


* HashMapT 의 key를 String으로 할 경우 컴파일 에러가 발생한다. 예제대로 int를 key값으로 사용하라.

2014년 5월 1일 목요일

Regarding Tizen native REST client app development (HTTP, JSON parser, Event-driven thread)

아래 내용은 Tizen 2.2 기반이라 상위 버전에서는 별 의미 없는 내용입니다.
--------------------------------------------------------------------------- Tizen native app으로 REST client app을 개발하고자
관련된 tutorial 링크 및 참고 사항들을 대충 정리 함...

- HTTP request/response 처리
- JSON parsing
- HTTP response 처리를 위한 Event-driven thread 사용

[HTTP transaction concept]

https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/net/http_transaction.htm

REST client app을 만드니... 기본적인 HTTP transaction에 대해서는 이해가 필요하겠지..

 . HTTP transaction 에 대한 내용들
http://www.pearsonhighered.com/assets/hip/us/hip_us_pearsonhighered/samplechapter/0672324547.pdf



http://www.w3.org/2002/Talks/www2002-p3p/all.htm

 . Chunked transfer
  : 간단히 말하면 일반적인 http streaming transfer는 content를 response로 한번에 보내지만 chunked transfer는 content를 임의의 크기로 쪼개서 보냄. 이런 경우는 server측의 performance의 제약이나 전달되는 content가 실시간 생산되는 content의 경우(크기를 예측할 수 없음) 이런 방법을 사용.
  : Tizen HTTP transfer default mode는 Non chunked transfer mode 이지만 일반적인 server에서는 chunked transfer 지원.
  : http://en.wikipedia.org/wiki/Chunked_transfer_encoding

[HTTP request/response]


[HttpClient Sample Overview]
: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/sample_descriptions/httpclient.htm



HTTP request를 전송하고 response의 body bytes 수를 표시하는 sample app.
tizen.org 를 대상으로 HTTPS request를 실행하므로 외부 network으로 연결에 문제가 없는 지 확인 필요. (proxy 같은)

[HTTP Client]
https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/tutorials/net_tutorial/task_httpclient.htm

* HTTP request 시 http transaction을 asynchronous 하게 처리하기 위해 아래 IHttpTransactionEventListener 등록이 필요

Tizen::Net::Http::IHttpTransactionEventListener
: https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Net_1_1Http_1_1IHttpTransactionEventListener.html

  • OnTransactionAborted
  • OnTransactionCertVerificationRequestedN
  • OnTransactionCertVerificationRequiredN
  • OnTransactionCompleted
  • OnTransactionHeaderCompleted
  • OnTransactionReadyToRead
  • OnTransactionReadyToWrite


HTTP-GET 시나리오에서
no chunked transfer에서는 response header 전달 이후 전체 body가 전송되므로 다음과 같은 이벤트가 발생할 것이고

Client   event                                                                         Server
                                                 GET request >
 HeaderCompleted event        < response header
 Completed event                   < response body

chunked transfer에서는 response header 전달 이후 body가 나눠서 오므로 다음과 같은 이벤트가 발생할 것이다.

Client    event                                                                        Server
                                                 GET request >
 HeaderCompleted event        < response header
 ReadyToRead event               < response body
 ReadyToRead event               < response body
 ReadyToRead event               < response body
 Completed event                   < response body

HTTP-POST 시나리오는 아마도 이렇지 않을까? (해보지는 않음.)

Client     event                                                                       Server
                                          POST request header >
ReadyToWrite event                  request data >
ReadyToWrite event                  request data >
ReadyToWrite event                  request data >
ReadyToWrite event                  request data >
 Completed event                   < response body


[주의 및 참고]

* HTTP transfer를 app에서 사용 하려면 http privilege가 필요
  . manifest.xml > privileges > http://tizen.org/privilege/http

* HttpSession의 copy constructor가 private 인 관계로 reference를 사용할 수 없음

* 일반적인 얘기겠지만 HttpSession의 instance를 http transaction 중 유지하지 않으면 listener 호출 중 crash 발생됨.

* Http request 시 특정 사용자 정보를 response callback에서 확인하려면 HttpTransaction의 SetUserObject()를 사용하라 HttpTransaction instance는 request, response시 모두 접근할 수 있음.
 : https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Net_1_1Http_1_1HttpTransaction.html#a8eff3be989218969838e76310cf99706


[HTTP programming guide]

나머지 항목들은 한번 보시라.

The most common uses of HTTP connectivity are the following:
https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/net/http_connectivity.htm


[JSON]


Introduction to JSON on Tizen
https://developer.tizen.org/documentation/articles/introduction-json-on-tizen

JSON Parser App
https://developer.tizen.org/dev-guide/2.2.0/?topic=%2Forg.tizen.native.appprogramming%2Fhtml%2Ftutorials%2Fweb_tutorial%2Ftask_jsonparserapp.htm

이 예제에서는 JSON data를 parsing해서 key, value list를 제공해 주는 예제다.
단지 JSON data인 string을 parsing해서 탐색 가능한 data structure로 제공해 준다는 의미만 있을 뿐.. 그 이상의 편의는 제공하지 않는다.
사용자가 json response를 직접 parsing 해서 원하는 value를 가져오거나 utility 함수를 만들어서 key에 맞는 value를 가져오도록 해야 할듯.

   // Call JSON parser
   IJsonValue* pJson = JsonParser::ParseN(buf);

   __pJsonKeyList->RemoveAll(true);
   __pValueList->RemoveAll(true);
   TraverseFunction(pJson);


void
JsonForm::TraverseFunction(IJsonValue* pValue)
{   
   switch (pValue->GetType())
   {
      case JSON_TYPE_OBJECT:
      {
         JsonObject* pObject = reinterpret_cast< JsonObject* >(pValue);
         IMapEnumeratorT<const String*, IJsonValue*>* pMapEnum = pObject->GetMapEnumeratorN();

         while (pMapEnum->MoveNext() == E_SUCCESS)
         {

...
 case JSON_TYPE_STRING:
      {
         JsonString* pVal = reinterpret_cast< JsonString* >(pValue);
...
 case JSON_TYPE_ARRAY:
      {
         JsonArray* pJsonArray = static_cast< JsonArray* >(pValue);
         pJsonArray->GetCount();
         IEnumeratorT<IJsonValue*>* pEnum = pJsonArray->GetEnumeratorN();
         while (pEnum->MoveNext() == E_SUCCESS)
...
...

[Alternatives JSON parsers]

JsonCpp
: boost library 기반, library 생성을 위한 컴파일 필요
: http://jsoncpp.sourceforge.net/

cJSON
: simple, MIT license, 2013년이 최신 업데이트
: http://sourceforge.net/projects/cjson/

jsmn
: simple, MIT license, 아직 개발중으로 보임 2014년 최근까지 수정 내역 있음.
: https://bitbucket.org/zserge/jsmn/overview


다른 대안을 찾아 보니 위의 것들이 있었고 http://www.json.org/ 중간에 보면 각 언어에 맞는 json parser library들이 존재하니 알아서 취사 선택하면 될듯함.

간단하게 사용하고자 cJSON을 사용하였고 사실 Tizen에서 제공하는 JSON parser와 기능은 거의 동일하지만 c style로 api 사용 및 array 처리가 간단하다.
JsonCpp도 많이 사용하고 편리한 사용성의 api들을 제공하지만 boost library를 사용하므로 boost library의 cross compile이 필요하고 소스의 양도 좀 되서 그냥 패스함.


cJSON을 통해 parsing하면 cJSON* 이 리턴되고 이를 사용해서 key에 맞는 value들을 뽑아 내면 됨.

typedef struct cJSON {
struct cJSON *next,*prev;     /* next/prev allow you to walk array/object chains.
                                                      Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */

struct cJSON *child;             /* An array or object item will have a child pointer pointing to
                                                        a chain of the items in the array/object. */


int type; /* The type of the item, as above. */

char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */

char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;


일반적이 primitive value들은 list traversal 방법으로 확인하면 되며 array나 object들은 아래 함수를 사용해서 뽑아내면 된다.

/* Get Array size/item / object item. */
int          cJSON_GetArraySize(cJSON *array)
cJSON *cJSON_GetArrayItem(cJSON *array,int item)
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)


cJSON* element = null;
element = cJSON_GetObjectItem(item, "peoples");
if(null != element)
{
int size = cJSON_GetArraySize(element);
for(int i = 0 ; i < size ; i++)
{
cJSON* child_element = cJSON_GetArrayItem(element, i);
AppLog("peoples (%d) = %s - %s", i, child_element->string, child_element->valuestring);
...
}
element = null;
}

[Thread]

https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.appprogramming/html/guide/base/thread.htm

Tizen에서는 아래와 같은 두가지(Main thread 제외)의 thread model들이 사용할 수 있고 각각의 특색은 다음과 같음.

[Event-driven Thread]
https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Base_1_1Runtime_1_1EventDrivenThread.html
: Event-driven threads run based on events and they execute in a loop until they receive an event notification to terminate. Event-driven threads allow using asynchronous calls.

[Worker Thread]
https://developer.tizen.org/dev-guide/2.2.0/org.tizen.native.apireference/classTizen_1_1Base_1_1Runtime_1_1Thread.html
: Worker threads run linearly; they only execute the main body of the thread and exit. Asynchronous calls cannot be used, since the thread does not run an event-loop.




주기적인 HTTP request/response를 처리하고자 할 경우 Event-driven thread를 사용해야 함. 단순 http request/reponse를 처리할 때는 상관없으나 loop을 사용할 경우 worker thread에서는 바로 error가 발생하는 것으로 보인다. 실제 tizen platform에서 처리하는 방법은 알 수 없으나 주기적으로 반복해야 하는 상황에서는 event driven thread를 사용하는게 필요 함.

사용상의 별 특이점은 없음. 예제대로 만들면 잘 돌아감.. ㅎ