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);
}


댓글 없음:

댓글 쓰기