Android - Hybrid App
스마트폰 OS인 Android에서 Hybrid App 관련 사항을 정리 한다.
목차
하이브리드 앱
제가 생각하는 하이브리드 앱은 모바일 앱과 모바일 웹(HTML5)이 서로의 장점을 살려서 모바일 환경을 더욱 풍요롭게 하는 것을 의미 합니다. Android에서는 하이브리드 앱을 구현하기 위해서 WebView를 사용 합니다.
권한 설정
- AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
화면 설정
- /res/layout/~.xml
<WebView android:id="@+id/webview" android:layout_width="fill_parent" android:layout_height="fill_parent" />
Web 화면
- HTML Page
- ratio : 0.75, 1.0, 1.5
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio: 1.0)" href="mdpi.css" /> <style type="text/css" media="screen"> @media screen and (-webkit-device-pixel-ratio: 1.0) { } </style> <script type="text/javascript"> if (window.devicePixelRatio == 1.0) { } </script>
Activity 구현
- Activity
private WebView browser = null; private Activity activity = null; public void onCreate(Bundle savedInstanceState) { WebSettings setting = null; super.onCreate(savedInstanceState); setContentView(R.layout.smarthybrid); activity = this; browser = (WebView) findViewById(R.id.website); setting = browser.getSettings(); setting.setJavaScriptEnabled(true); browser.setWebViewClient(new ProxyWebViewClient()); browser.setWebChromeClient(new ProxyWebChromeClient()); //--- 프로젝트의 /assets 폴더에 test.html 파일을 추가 //--- browser.loadUrl("file:///android_asset/test.html"); //--- browser.loadData("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />한글", "text/html", "utf-8"); browser.loadUrl(website); //--- byte[] post = EncodingUtils.getBytes("a=b&c=d&e=f", "BASE64"); //--- browser.postUrl("http://example.com/myform/", post); } public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && browser.canGoBack()) { browser.goBack(); return true; } return super.onKeyDown(keyCode, event); } private class ProxyWebViewClient extends WebViewClient { public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("tel:")) { Intent i = new Intent(Intent.ACTION_CALL, Uri.parse(url)); startActivity(i); } else { view.loadUrl(url); } return true; } public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show(); } } private class ProxyWebChromeClient extends WebChromeClient { public boolean onJsAlert(WebView view, String url, String message, JsResult result) { Toast.makeText(activity, message, 3000).show(); result.confirm(); return true; } }
- WebView에서 HTML5 사용을 위한 WebSettings 설정
WebSettings setting = null; browser = (WebView) findViewById(R.id.website); setting = browser.getSettings(); setting.setJavaScriptEnabled(true); //--- JavaScript 허용 setting.setGeolocationEnabled(true); //--- 위치 정보 사용 허용 setting.setJavaScriptCanOpenWindowsAutomatically(true); setting.setLoadsImagesAutomatically(true); setting.setPluginsEnabled(true); setting.setLightTouchEnabled(true); setting.setSupportZoom(true); setting.setBuiltInZoomControls(true); //--- HTML5에서 Database를 설정 한다. setting.setDatabaseEnabled(true); //--- HTML5에서 Database 허용 //--- Database를 위해 WebChromeClient.onExceededDatabaseQuota(~) 함수도 같이 설정할 것 setting.setDatabasePath("/data/data/com.jopenbusiness.android.smarthybrid/database"); //--- HTML5에서 DOM Storage를 설정 한다. setting.setDomStorageEnabled(true); //--- HTML5 DOM Storage 허용 //--- HTML5에서 Cache 설정을 한다. //--- Database를 위해 WebChromeClient.onReachedMaxAppCacheSize(~) 함수도 같이 설정할 것 setting.setAppCacheMaxSize(1024 * 1024 * 8); //--- Default Cache Size를 8 MB로 설정 setting.setAppCachePath("/data/data/com.jopenbusiness.android.smarthybrid/cache"); setting.setAppCacheEnabled(true); setting.setAllowFileAccess(true); setting.setCacheMode(WebSettings.LOAD_DEFAULT);
Cookie 동기화 처리
- Activity에서 Cookie 동기화 처리
private WebView browser = null; public void onCreate(Bundle savedInstanceState) { CookieSyncManager.createInstance(this); } public void onStart() { super.onStart(); browser = (WebView) findViewById(R.id.website); browser.setWebViewClient(new ProxyWebViewClient()); CookieSyncManager.createInstance(this); } protected void onResume() { super.onResume(); CookieSyncManager.getInstance().startSync(); } protected void onPause() { super.onPause(); CookieSyncManager.getInstance().stopSync(); } private class ProxyWebViewClient extends WebViewClient { public void onPageFinished(WebView view, String url) { CookieSyncManager.getInstance().sync(); } }
Progress Bar 표시
앱의 타이틀바에 웹페이지 로딩 진행 상태(Progress Bar)를 표시 한다.
- Activity에 다음을 추가 한다.
private WebView browser = null; private Activity activity = null; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //--- setContentView(~) 앞에 다음 라인을 추가 한다. getWindow().requestWindowFeature(Window.FEATURE_PROGRESS); setContentView(R.layout.main); activity = this; this.setTitle("앱 타이틀"); browser = (WebView) findViewById(R.id.website); browser.setWebChromeClient(new ProxyWebChromeClient()); } public class ProxyWebChromeClient extends WebChromeClient { public void onProgressChanged(WebView view, int newProgress) { activity.setTitle("로딩 ..."); activity.setProgress(newProgress * 100); if (newProgress == 100) { activity.setTitle("앱 타이틀); } } }
앱과 웹의 통신
- Activity에서 다음과 같이 구현 한다.
import android.os.Handler; private WebView browser = null; private final Handler handler = new Handler(); public void onCreate(Bundle savedInstanceState) { WebSettings setting = null; browser = (WebView) findViewById(R.id.website); setting = browser.getSettings(); setting.setJavaScriptEnabled(true); browser.addJavascriptInterface(new Hybrid(), "hybrid"); } private class Hybrid { public void setMessage(final String arg) { handler.post(new Runnable() { public void run() { Log.d("Hybrid", "setMessage("+arg+")"); mTextView.setText(arg); } }); } } //--- JavaScript에서 App 호출 window.hybrid.setMessage(msg); //--- App에서 JavaScript 호출 browser.loadUrl("javascript:setMessage('message')");
화면 회전 금지
- WebView 화면이 회전되지 않도록 하려면, 화면 회전에서 "화면이 회전해도 Activity가 다시 로딩되지 않도록 하는 방법"을 참조 하세요.
WebView의 HTML5 지원
- Android 2.2의 WebView의 HTML5 지원 점수
참고 문헌
- Android 매뉴얼
- HTML5
- Android, Hybrid apps and HTML5 databases
- Sony Ericsson의 WebSDK Packager : 모바일 웹 개발을 위한 도구