Android 플랫폼에서 Tizen 애플리케이션 실행
PUBLISHED
필수 구성 요소
이 문서에 연결된 모든 애플리케이션에는 Android 버전 2.2 이상이 있는 Android 장치가 필요합니다.
소개
Android 플랫폼의 Tizen HTML5 애플리케이션을 실행하기 전에 "Tizen 웹 애플리케이션의 뛰어난 이식성 유지" 문서에 자세히 설명되어 있는 확장 가능한 애플리케이션 UI에 대한 개발 프로세스를 수행해야 합니다. 이러한 절차를 따르지 않을 경우 애플리케이션의 UI가 다양한 Android 장치에서 확장되지 않습니다. UI 확장은 Android 플랫폼 자체에서 수행될 수 있으므로 필수가 아닙니다. Android가 애플리케이션 기능을 확장하거나 축소하는 경우 바람직하지 않은 결과물이 생성될 수 있으므로 사실상 권장되는 접근 방법이 아닙니다.
Android 플랫폼에서 HTML5 애플리케이션(Tizen 웹 애플리케이션)을 실행하는 방법은 여러 가지가 있습니다. 가장 일반적인 방법은 다음과 같습니다.
- PhoneGap/Cordova를 사용하여 프로젝트를 빌드합니다. 이 방법을 사용하여 HTML5 애플리케이션을 생성하며 PhoneGap은 Android, iOS, Windows Mobile, bada 등 여러 하드웨어 플랫폼에 대한 기본 빌드를 자동으로 생성합니다. PhoneGap은 JavaScript와 기본 플랫폼 API 사이에서 다리 역할을 하는 자체 API를 제공합니다.
- 나만의 래퍼 애플리케이션을 생성하고 HTML5 애플리케이션을 내부에 애플리케이션을 내부에 포함합니다.
- HTML5 애플리케이션을 생성하기 위해 특정 프레임워크를 사용합니다. 일반적으로 이러한 프레임워크는 일부 기본 플랫폼에 대한 애플리케이션을 빌드하는 도구(Android 포함)를 제공합니다. 이러한 프레임워크에 대한 좋은 예는 Sencha Touch입니다.
이 문서에서는 Android 장치에 이전에 개발된 Earth Guard 1.0.3 애플리케이션을 실행하기 위해 첫 번째와 두 번째 방법을 사용하는 방법을 알려줍니다. 이 문서에 연결된 두 개의 프로젝트가 있습니다.
- 첫 번째 방법에 해당하는 EarthGuardPhoneGapExample
- 두 번째 방법에 해당하는 AndroidEarthGuard
또한 두 가지 방법 모두의 장단점을 알려줍니다.
첫 번째 방법과 두 번째 방법에 대해 Android 기본 애플리케이션에 HTML5 애플리케이션을 포함한다는 개념이 비슷합니다. 유일한 차이점은 PhoneGap이 기본 Android API 클래스에 대해 래퍼로 작동하는 클래스를 제공한다는 것입니다.
HTML5 애플리케이션은 Android Activity 내부에 있는 WebView 개체 인스턴스에 포함됩니다. HTML5 애플리케이션은 예를 들어 WebAppInterface 클래스의 인스턴스를 사용하여 Java Android 래퍼와 통신할 수 있습니다. WebView를 통해 반대 방향으로 통신할 수 있습니다.
그림 1: Android 애플리케이션에 포함된 HTML5 애플리케이션의 기본 개념.
그림 2: 삼성 갤럭시 S3의 Earth Guard
PhoneGap/Cordova를 사용하여 Android용 Tizen HTML5 애플리케이션 빌드
PhoneGap을 시작하는 가장 쉬운 방법은 PhoneGap 패키지에 첨부되어 있는 예제 청사진 애플리케이션을 사용하는 것입니다. 다운로드 사이트에서 최신 Cordova 패키지를 다운로드할 수 있습니다. Android용 PhoneGap 예제 애플리케이션은 /lib/android/example에서 찾을 수 있습니다.
청사진 예제를 애플리케이션에 대한 시작점으로 사용하려는 경우 다음 단계를 수행하십시오.
- Java, Android SDK 및 Ant가 설치되어 있어야 합니다. 이 소프트웨어의 설치는 이 문서의 범위에 있지 않습니다.
- 다음 프로그램(android, ant, adb)을 포함하도록 환경 변수 PATH를 업데이트하십시오.
- PhoneGap 디렉토리에서 ./phonegap/lib/android로 이동하고 예제 폴더를 아무 위치에 복사합니다.
- ./example/assets/www를 ./example/assets/www_org로 변경합니다.
- 새 디렉토리 ./example/assets/www를 생성합니다.
- HTML5 애플리케이션을 ./Example/assets/www로 복사합니다. 이 시점에서 유일한 요구 사항은 유효한 HTML5 index.html 파일을 보유하는 것입니다. CSS 또는 JavaScript 파일이 필요하지 않습니다.
- ./example/cordova 디렉토리로 이동
- 셸에서 다음 명령 실행: android update project -p../ --target android-17
- 프로젝트 지우기 ./clean
- 프로젝트 빌드 ./build
- Android 장치를 Android OS에 연결 >= 2.1
- 애플리케이션 실행: ./run
- 이제 애플리케이션을 불러내고 Android 장치에서 실행해야 합니다. Index.html 파일이 화면에 렌더링됩니다.
이는 Android 장치에서 Earth Guard 게임이 완전히 실행될 때 종료되는 기나긴 여정의 시작일 뿐입니다.
Android 프로젝트를 Android Eclipse IDE로 가져와야 합니다. 이렇게 하려면 다음이 단계를 따르십시오.
- Android SDK가 설치된 Eclipse IDE를 실행합니다.
- 기존 코드에서 파일->새로 만들기->Android 프로젝트로 이동하고 이전에 생성한 Android PhoneGap 애플리케이션(예제 애플리케이션)을 가져옵니다.
- 패키지 탐색기의 컨텍스트 메뉴에서 cordovaExample 프로젝트를 선택하고 속성 -> Android로 이동합니다. 여기서 사용할 수 있는 최신 API 버전을 선택해야 합니다. 이러한 경우에는 Android 4.2를 선택합니다.
이제 Eclipse IDE의 Android PhoneGap 애플리케이션을 개발, 디버깅 및 배포할 수 있습니다.
JavaScript 애플리케이션 내부에 있는 console.log 호출을 사용하여 Android PhoneGap 애플리케이션을 디버깅할 수 있습니다. 디버그 메시지를 필터링하기 위해 설정된 태그:cordova가 있는 LogCat을 관찰해야 합니다. 전체 개체의 속성을 보거나 탐색할 수 없지만, 간단한 문자열 메시지만 LogCat에 사용할 수 있습니다.
이 시점에서 애플리케이션은 전체 PhoneGap API를 사용할 수 없으므로 해당 기능의 절반만 사용하는 중입니다. PhoneGap API에 대한 전체 문서는 여기에 있습니다. 다음 단계는 index.html에 cordova-2.5.0.js 파일을 포함하는 것입니다. 이렇게 하면 애플리케이션의 PhoneGap API를 사용할 수 있습니다. 애플리케이션의 소스 코드(장치 준비 이벤트 수신기 등록)에서 수행해야 할 필수 변경 사항이 딱 하나 있습니다. ./assets/www/js/main.js 파일을 참조하십시오.
document.addEventListener("deviceready", function() { if (view.checkEnviroment()) { game.inputHandler = inputHandler(); levelManager.init(); view.resize(); view.setPowerState("SCREEN_BRIGHT"); game.initialize(); } }, true);
장치 준비 이벤트는 초기화가 완료되면 Cordova WebView에 의해 트리거되며, 이 이벤트가 트리거된 후 HTML5 애플리케이션의 모든 작업이 완료되어야 합니다. 그렇지 않으면 PhoneGap API의 일부를 사용할 수 없습니다.
이는 필수지만 Android의 Earth Guard용 전체 UX를 제공하기 위해서는 다음을 수행해야 합니다.
- 활동 수명 주기 처리
- 장치 뒤로 버튼 처리
- 종료 버튼 처리
- 블록 방향 변경 - 샘플 애플리케이션은 가로 보기를 지원하지 않습니다.
애플리케이션 수명 주기 및 뒤로 버튼 처리
애플리케이션 수명 주기 및 뒤로 버튼 처리는 phoneGapHandler 모듈(./assets/www/js/modules/phoneGapHandler.js)에서 적절한 이벤트를 바인딩하는 문제에 불과합니다. 다음 코드를 참조하십시오.
/** * Module responsible for handling all phoneGap functionalities for application */ "use strict"; var phoneGapHandler = function() { var _init = function() { /** * Cordova back button handler */ document.addEventListener("backbutton", menu.toggle, false); /** * Cordova application life cycle handling */ document.addEventListener("pause", game.onHidden, false); document.addEventListener("resume", game.onVisible, false); }; return { init : _init }; }();
종료 버튼 처리
애플리케이션을 닫기 위해서 별도 PhoneGap API 호출을 제공해야 합니다. 게임 모듈(./assets/www/modules/game.js)에서 exit 메서드를 참조하십시오.
exit : function() { // Tizen exit handler if (typeof tizen !== "undefined" && tizen.application) { if (confirm("Exit?")) { var app = tizen.application.getCurrentApplication(); app.exit(); } // PhoneGap exit handler } else if (typeof navigator.app.exitApp !== "undefined") { navigator.app.exitApp(); } else { alert("Not supported"); } },
블록 방향 변경
앱 방향은 AndroidManifest.xml 파일에서 세로로 고정될 수 있습니다. 아래에서 적절한 코드를 참조하십시오.
"cordovaExample" android:label="@string/app_name" android:theme="@android:style/Theme.Black.NoTitleBar" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:screenOrientation="portrait">
나만의 Java 래퍼를 사용하여 Android용 Tizen HTML5 애플리케이션 빌드
이 방법은 약간 더 어렵지만 더욱 유연합니다. HTML5 애플리케이션 내부에서 노출할 Android API를 결정할 수 있으며 반대의 경우도 마찬가지이지만, 직접 구현해야 합니다. 여기서는 새로운 Android 프로젝트를 생성하는 방법과 WebView와 WebAppInterface를 MainActivity에 추가하는 방법을 자세히 보여주지 않습니다. 이에 대한 별도 자습서는 http://developer.samsung.com/android에서 찾을 수 있습니다.
HTML5 애플리케이션용 Java Android 래퍼를 구축하려면 다음과 같은 문제를 고려해야 합니다.
- Java 래퍼 및 HTML5 애플리케이션 간의 인터페이스 제공
- JS 애플리케이션의 console.log 메시지 처리 및 LogCat에 전달
- 뒤로 버튼 처리
- Android 애플리케이션 수명 주기 처리
- 전원 관리 처리
Java 래퍼 및 HTML5 애플리케이션 간의 인터페이스 제공
Java 애플리케이션과 HTML5 애플리케이션 간의 양방향 통신을 제공할 수 있습니다. HTML5 애플리케이션에 대해 노출되어야 하는 Android API 일부를 결정할 수 있습니다. 이러한 경우 이 API는 ./src/com/Samsung/srpol/androidearthguard/WebAppInterface.java 파일에 정의됩니다.
/** * Method available in JS application */ @JavascriptInterface public void exitApplication() { mActivity.finish(); } /** * Method available in JS application */ @JavascriptInterface public void setScreenOn(boolean screenOn) { mActivity.setScreenOn(screenOn); }
이러한 두 가지 메서드는 Android 네임스페이스의 HTML5 애플리케이션 내부에서 사용할 수 있습니다. 이 네임스페이스는 MainActivity에서 Android 래퍼 내부에 정의됩니다.
@SuppressLint("SetJavaScriptEnabled") private void initWebView() { … // Provides Android namespace in JS application mWebView.addJavascriptInterface(mWebAppInterface, "Android"); … }
게임 모듈에서 HTML5 애플리케이션 내부의 네임스페이스에 정의된 메서드를 사용합니다.
exit : function() { … Android.exitApplication(); … },
또한 view.js 모듈에서:
setPowerState : function(type) { … Android.setScreenOn((type === "SCREEN_BRIGHT") ? true : false); … },
HTML5 애플리케이션의 각 메서드는 Java 래퍼 내부에서 호출될 수 있습니다. 그렇게 하기 위해서는 WebView.loadUrl 메서드를 사용해야 합니다.
./src/com/Samsung/srpol/androidearthguard/MainActivity.java에 예제가 포함됩니다.
public boolean onKeyDown(int keyCode, KeyEvent event) { // Back button handler if ((keyCode == KeyEvent.KEYCODE_BACK)) { Log.d(this.getClass().getName(), "back button pressed"); mWebView.loadUrl("javascript:menu.toggle()"); return false; } return super.onKeyDown(keyCode, event); }
JS 애플리케이션의 console.log 메시지 처리 및 LogCat에 전달
적절한 디버깅 메커니즘 없이 HTML5 애플리케이션의 console.log 메시지는 LogCat에 표시되지 않습니다. console.log 메시지를 LogCat에 전달해야 합니다.
mWebView.setWebChromeClient(new WebChromeClient() { public boolean onConsoleMessage(ConsoleMessage cm) { Log.d(getString(R.string.js_console_tag), "[EarthGuard]: " + cm.message() + " -> line(" + cm.lineNumber() + ") of " + cm.sourceId()); return true; } });
샘플 애플리케이션의 각 메시지는 [EarthGuard] 문자열을 사용하여 태그가 지정되며 LogCat의 태그 상자를 사용하여 쉽게 필터링할 수 있습니다.
뒤로 버튼 처리
애플리케이션의 뒤로 버튼을 처리할지 여부를 결정할 수 있습니다. Earth Guard 샘플 애플리케이션에서 메뉴 토글 메서드를 Android 뒤로 버튼에 추가하기로 했습니다. 아래의 코드를 참조하십시오.
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { // Back button handler if ((keyCode == KeyEvent.KEYCODE_BACK)) { Log.d(this.getClass().getName(), "back button pressed"); mWebView.loadUrl("javascript:menu.toggle()"); return false; } return super.onKeyDown(keyCode, event); }
Android 애플리케이션 수명 주기 처리
Android 활동 수명 주기는 복잡합니다. 자세한 내용은 여기를 참조하십시오. HTML5 애플리케이션은 일부만 처리해야 합니다.
- 활동이 배경으로 전송되는 경우 game.onHidden() 메서드를 호출해야 합니다.
- 활동이 전경으로 전송되는 경우 game.onVisible() 메서드를 호출해야 합니다.
아래의 코드를 참조하십시오.
/** * Triggers game.onVisible() method in JS application * */ @Override protected void onResume() { super.onResume(); Log.d(this.getClass().getName(), "Main activity onResume()"); mWebView.loadUrl("javascript:game.onVisible()"); if (mScreenOn) { mWakeLock.acquire(); } } /** * Triggers game.onHidden() method in JS application * */ @Override protected void onPause() { super.onPause(); Log.d(this.getClass().getName(), "Main activity onPause()"); mWebView.loadUrl("javascript:game.onHidden()"); if (mWakeLock.isHeld()) { mWakeLock.release(); } }
전원 관리 처리
게임을 하는 동안 화면이 흐릿해지는 현상을 방지하려면 전원 관리를 구현해야 합니다. Earth Guard 게임에서 PowerManager 클래스와 깨우기 잠금이 사용되었습니다. 매니페스트 파일의 특별 허가가 필요합니다.
"android.permission.WAKE_LOCK" />
깨우기 잠금을 사용하면 전력 소모량이 현저하게 증가하므로 필요할 경우에만 사용해야 합니다. Earth Guard 게임에서 사용자가 게임 보기를 사용하는 동안 화면이 흐릿해지지 않도록 방지하려고 합니다. 전원 관리에 관한 모든 논리는 MainActivity에 있습니다. JavaScript 부분에서 사용할 수 있는 유일한 함수는 setScreenOn(Boolean screenOn) 메서드입니다.
/** * Method available in JS application. Switch on/off preventing the screen from dimming * * @param screenOn * true if we want to prevent the screen from dimming, false if we want to release it */ @JavascriptInterface public void setScreenOn(boolean screenOn) { mActivity.setScreenOn(screenOn); }
나중에 언급될 MainActivity의 setScreenOn() 메서드를 호출합니다.
전원 관리를 구현하는 동안 mainActivity 클래스에 두 개의 추가 필드를 추가했습니다.
private PowerManager.WakeLock mWakeLock; private boolean mScreenOn = false;
첫 번째 필드 mWakeLock은 사용될 WakeLock 개체입니다. 두 번째 필드는 화면이 강제로 켜져 있어야 하는지 여부를 나타내는 플래그입니다. 그 값은 위에서 언급한 setScreenOn 함수에 의해 설정됩니다.
깨우기 잠금을 사용하면 꽤 간단합니다. WakeLock 클래스의 인스턴스를 생성한 다음 두 가지 사용 가능한 함수를 사용해야 합니다.
- acquire()
- release()
protected void onCreate(Bundle savedInstanceState) { ... PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "MainActivity"); ... }
NewWakeLock(int levelAndFlags, 문자열 태그) 함수는 두 개의 매개 변수를 가져옵니다. 첫 번째 매개 변수는 깨우기 잠금 수준 및 선택적 플래그를 지정합니다. 가능한 수준은 4가지가 있습니다.
- PARTIAL_WAKE_LOCK,
- FULL_WAKE_LOCK,
- SCREEN_DIM_WAKE_LOCK,
- SCREEN_BRIGHT_WAKE_LOCK
EarthGuard에서 SCREEN_BRIGHT_WAKE_LOCK 플래그를 사용했습니다. 화면이 최대 밝기로 켜져 있고 흐릿해질 수 없도록 합니다. NewWakeLock 함수에서 두 번째 인수는 디버깅 목적으로 사용된 플래그입니다.
이제 acquire() 및 release() 함수를 사용할 수 있습니다.
public void setScreenOn(boolean screenOn) { mScreenOn = screenOn; if (screenOn && !mWakeLock.isHeld()) { mWakeLock.acquire(); } else if (!screenOn && mWakeLock.isHeld()) { mWakeLock.release(); } }
SetScreenOn 메서드는 하나의 매개 변수 screenOn을 가져옵니다. 화면이 흐릿해지는 현상을 방지하려면(true screenOn) mWakeLock.acquire() 메서드를 사용합니다. 이를 수행하기 전에 mWakeLock.isHeld() 메서드로 이미 활성 상태에 있지 않은지 확인해야 합니다. 깨우기 잠금을 해제하려면 mWakeLock.release() 메서드를 사용합니다.
또한 애플리케이션이 배경으로 이동하고 다시 시작하는 경우 깨우기 잠금을 올바르게 처리하는 것도 중요합니다.
@Override protected void onResume() { super.onResume(); ... if (mScreenOn) { mWakeLock.acquire(); } } @Override protected void onPause() { super.onPause(); ... if (mWakeLock.isHeld()) { mWakeLock.release(); } }
OnResume()에서 깨우기 잠금이 켜져 있어야 하는지 확인하고(mScreenOn 플래그가 true로 설정) 켜진 경우 가져옵니다. OnPause() 함수에서 깨우기 잠금이 활성화되어 있는지 확인하고 활성화된 경우 해제합니다.
요약
Android만 |
HTML5 애플리케이션에서 사용 가능한 장치 API |
최소 Android 버전 |
권장 Android 버전 |
Java 및 HTML5 애플리케이션 간의 인터페이스 |
|
전용 Java 래퍼 |
예 |
아니요(*) |
2.2 API8 |
4.2 API17 |
예 |
PhoneGap/Cordova 방법 |
아니요 |
예 |
2.1 API7 |
4.2 API17 |
아니요 |
PhoneGap 방법 및 전용 래퍼 방법의 비교를 보여주는 표
(*) – 직접 제공해야 합니다
전용 Java 래퍼가 PhoneGap 보다 더 나은 특정 경우도 있습니다.
- Android 장치에서만 HTML5 애플리케이션을 실행하려는 경우
- Android API에서 HTML5 애플리케이션까지 몇 가지 특정 기능을 제공하려는 경우
다른 경우에는 PhoneGap 방법을 사용하는 것이 좋습니다.