메인 컨텐츠로 가기

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관 보기.

모든 정보가 안전하게 전송되었습니다.

  • 닫기 [x]

Android에서 XML과 JSON 사용하기, Part 2: JSON을 사용하여 하이브리드 Android 애플리케이션 전달하기

Android-SDK Java 코드, Javascript, JSON, 콜백 함수를 결합하여 유연한 모바일 애플리케이션을 빌드한다.

Frank Ableson, Software designer
대학에서 야구 선수로 활동한 후 L.A. Lakers와의 다년 계약을 맺지 못한 Frank Ableson은 컴퓨터 소프트웨어 설계로 관심을 돌렸다. 복잡한 문제 해결을 좋아하는 그는 특히 통신 및 하드웨어 인터페이스 분야에 많은 관심을 가지고 있다. 부인인 Nikki와 자녀들과 함께 여가 시간을 보내는 단란한 가정의 가장이기도 하다. 그의 이메일 주소는 frank@cfgsolutions.com이다.

요약:  두 개의 파트로 구성된 이 시리즈 기사에서는 현재 인터넷에서 사용하는 가장 일반적인 데이터 형식인 XML과 JSON(JavaScript Object Notation)을 Android 플랫폼에서 처리하는 기술을 살펴봅니다. Part 1에서는 XML과 JSON의 기본적인 사항을 살펴봅니다. Part 2에서는 Webkit으로 호스트하는 Javascript 코드와 Android 애플리케이션의 Java™ 코드 간에 데이터를 교환하는 방법을 살펴봅니다. 이 기사에서는 가장 유용하고 유연한 방식으로 여겨지는 JSON에 대해 집중적으로 살펴봅니다.

이 연재 자세히 보기

원문 게재일:  2010 년 8 월 24 일 번역 게재일:   2010 년 12 월 07 일
난이도:  중급 원문:  보기 PDF:  A4 and Letter (235KB | 20 pages)Get Adobe® Reader®
페이지뷰:  8217 회
의견:  


이 기사에 있는 예제 코드를 실행하려면 Eclipse와 Android SDK 버전 1.5 이상을 설치해야 한다. 환경 설정과 관련된 정보는 Android Developers 웹 사이트를 참조한다. 링크는 참고자료를 참조한다.

소개

휴대전화는 가장 인기 있는 기술 분야이다. 다양한 플랫폼이 판매량과 인지도 면에서 업계 최고의 위치에 오르기 위해 경쟁하고 있다. 이러한 플랫폼은 첨단 기술의 표본이고 할 수 있지만 이러한 플랫폼의 인기가 더욱 많아지는 이유는 이러한 플랫폼에서 사용할 수 있는 매우 다양한 애플리케이션이 우수한 사용자 경험을 제공하기 때문이다. 특히, iPhopne과 Android 플랫폼은 모두 비즈니스 고객과 소비자 고객의 마음을 사로잡아서 이들의 지갑을 열기 위해 경쟁하고 있는 최신 디바이스이다.

자주 사용하는 약어

  • API: Application Programming Interface
  • CSS: Cascading Style Sheets
  • HTML: HyperText Markup Language
  • IDE: Integrated development environment
  • SDK: Software Developer Kit
  • UI: User Interface
  • XML: Extensible Markup Language

모바일 사용자가 사용할 수 있는 대다수의 애플리케이션은 각 플랫폼 벤더에서 제공하는 핵심 SDK를 통해 모바일 개발자가 작성한 것이다. 모바일 디바이스가 인기를 얻게 된 이유는 과거 10년 동안 웹에서 잔뼈가 굵은 다수의 유능한 웹 기술 프로그래머가 있었기 때문이며 이렇게 모바일 디바이스가 대중화되면서 새로운 애플리케이션 모델 즉, 웹 브라우저 인터페이스와 기본 모바일 컴포넌트 모두를 사용하는 애플리케이션인 하이브리드 애플리케이션이 탄생하게 되었다. 하이브리드 애플리케이션은 iPhone뿐만 아니라 Android에도 존재하지만 이 기사에서는 Android 하이브리드 애플리케이션과 관련된 내용과 Javascript 및 JSON을 사용하는 방법을 집중적으로 살펴본다.

하이브리드 애플리케이션은 Android의 WebView 제어에서 확인할 수 있는 WebKit을 기반으로 빌드된다. WebView는 WebKit의 기능을 Android 프로그래머에게 표시하는 사용자 인터페이스이다. 이러한 WebView 제어는 애플리케이션에서 원격 웹 페이지를 렌더링하고, 개발자와 사용자에게 익숙한 사용자 경험을 제공하며 원시 Android 애플리케이션에서 강력하고 유연한 Javascript 환경을 활용하기 위해 사용된다.

하이브리드 애플리케이션에서는 주로 사용자 인터페이스 요소에 WebKit의 기능을 이용하기 위해 WebView 위젯을 활용하는 경우가 많지만 하이브리드 애플리케이션이 단순히 WebView 위젯에 HTML을 표시하는 역할만 하는 것은 아니다. 하이브리드 애플리케이션의 기능은 다양하다. 다시 말해서 Android SDK에는 광범위한 기능이 포함되어 있고 이러한 기능은 HTML과 CSS, Javascript와 같은 웹 기술이 결합된 것이며 이러한 기능을 이용하면 상상할 수 있는 모든 형태의 하이브리드 애플리케이션을 작성할 수 있다. 하이브리드 애플리케이션의 개념을 조금 더 구체화하기 위해 이 기사에서는 Activity와 WebView 간의 다양한 상호작용을 구현하고 JSON을 사용하여 데이터를 교환하는 AndroidJSON 샘플 애플리케이션을 살펴본다. 이 애플리케이션에서는 WebView에서 호스트하는 Javascript 및 HTML, Activity 간의 다양한 상호작용과 Javascript 계산기와 같은 기본 기능을 확인할 수 있다.

먼저, Android 애플리케이션에 직접 WebKit 엔진을 임베드하는 과정을 살펴보자.


Android에 임베드된 Javascript 계산기

대부분의 SDK 기반 Android 애플리케이션에는 하나 이상의 Activity 클래스가 구현되어 있다. Activity 클래스는 본질적으로 애플리케이션 사용자가 경험하게 되는 사용자 인터페이스 요소가 포함된 화면이나 페이지에 해당한다.

Activity에는 단추, 레이블, 텍스트 입력 상자 및 단일 선택 단추 목록과 같은 사용자 인터페이스 요소(개발자가 정의한)의 콜렉션이 표시된다. Android SDK에는 예상할 수 있는 모든 것이 존재한다. 이러한 사용자 인터페이스 요소 외에 WebView라고 하는 특수한 위젯도 존재한다.

Javascript 계산기에서는 Activity의 Java 환경과 WebView의 Javascript 환경이 함께 공존하고 있다는 것을 확인할 수 있다. 이 애플리케이션은 WebView를 통해 단순히 HTML 컨텐츠를 표시하는 기능 이상의 역할을 한다. 다시 말해서, 이 애플리케이션은 실제로 Java 환경을 연결하여 Javascript 환경에 기능을 제공하고 이 작업을 안전하게 수행하는 과정에서 두 환경을 통합하여 고유한 사용자 경험을 가능하게 한다. 두 환경이 연결되면 JSON 형태로 데이터를 교환하여 다양한 기능을 전달하게 되며 이 기사에서는 이러한 모든 과정을 전체적으로 다루게 된다. 그러면 먼저, Javascript 계산기에서 WebView 위젯이 어떻게 활용되고 있는지 살펴보도록 하자.

이 애플리케이션이 어떻게 구성되는지 세부적으로 살펴보기 전에 이 애플리케이션의 다양한 기능을 잠시 검토해보자. 그림 1에는 이 애플리케이션의 화면이 표시되어 있다.


그림 1. 작동 중인 Javascript 계산기 표시하기
작동 중인 Javascript 계산기를 캡처한 화면

본래의 샘플 Android 애플리케이션인 AndroidJSON에서는 Activity 컴포넌트를 사용하여 화면을 정의한다. 이 화면의 상반부에는 TextView(정적 레이블), EditText(사용자가 수식을 입력하는 텍스트 상자) 및 세 개의 단추(Simple, Complex 및 Make Red)와 같은 사용자 인터페이스 요소가 표시된다. 또한, Activity에는 화면 하반부를 표시하는 하나의 WebView 제어 인스턴스가 있다.

WebView는 Android 애플리케이션에 패키지된 HTML 파일(index.html)을 표시한다. (인터넷을 통해 이 파일을 직접 다운로드할 수 있다.) 이 웹 페이지에는 표제와 일부 샘플 텍스트, 계산 결과 그리고 다양한 기능을 수행하는 여섯 개의 단추(Log Info, Log Error, Dynamic, How Many Calls, History 및 Kill This App)가 표시된다.

이 프로젝트에서 중요한 파일은 Android 애플리케이션 코드인 AndroidJSON.java, index.html 웹 페이지 및 나중에 살펴볼 UI 레이아웃 파일인 main.xml이다. 이 파일에 대한 링크는 다운로드를 참조한다.

먼저, Activity에 있는 단추 세 개의 기능을 살펴보자.

Simple
Simple 단추를 클릭하면 EditText의 내용이 수학 표현식으로서 평가된다. EditText의 내용이나 수식은 WebView 제어로 전달되어 Javascript에서 평가된다는 점에 주목한다.
Complex
Complex 단추를 클릭하면 JSON 오브젝트가 WebView로 전송되어 평가된다. 이러한 과정은 오브젝트가 Javascript 코드에서 순차적으로 해석되어 수학적으로 처리된다는 사실로 인해 복잡하게 여겨진다. 이 단추를 클릭하면 정수 배열 요소를 더하는 함수와 동일한 정수 배열을 곱하는 함수가 서로 교체된다.
Make Red
세 번째 단추는 재미삼아 삽입한 것이다. 이 단추를 선택하면 임베드된 WebView 내용에 스타일이 적용되어 <body> 태그 내에 포함된 텍스트 요소의 색상이 빨간색으로 바뀐다.

이제 index.html 파일에 있는 함수를 살펴보자. 이러한 함수는 런타임 시에 임베드된 WebView 제어에 의해 활성화된다.

Log Info
이 단추는 Info 카테고리에 있는 애플리케이션 로그에 항목을 쓰는 콜백을 Android 애플리케이션에서 호출한다.
Error Info
이 단추는 Error 카테고리에 있는 애플리케이션 로그에 항목을 쓰는 콜백을 Android 애플리케이션에서 호출한다.
Dynamic
이 단추는 올바른 Javascript 코드를 표현하는 텍스트를 검색하는 콜백을 Android 애플리케이션에서 호출한다. 이 코드는 WebView로 되돌려져서 실행되며 애플리케이션의 Javascript 및 Java 코드 간에 발생하는 상호작용을 표시한다. 이 방식은 Javascript eval 함수에 대한 의존도가 너무 크기 때문에 다소 보안에 취약하다. 그러나 이 기사에서는 프로덕션 환경에서 즉시 사용할 수 있는 완전한 애플리케이션 대신 기본적 애플리케이션에 집중한다.
How many calls
콜백 함수가 호출될 때마다 카운터가 증가한다. 이 단추를 클릭하면 카운터가 표시된다.
History
Javascript 함수가 호출될 때마다 함수 이름이 표현된 문자열이 Javascript 배열에 추가된다. 이 배열은 History 단추가 호출될 때마다 JSON으로 변환되어 Android 애플리케이션의 기본 부분에 전달된다. 이 배열은 Java 코드에서 오브젝트로 재구성되며 해당 로그에 기록된 각 배열 요소와 함께 나열된다.
Kill This App
이 단추는 샘플 애플리케이션에서 구현된 또 다른 재미있는 기능 중의 하나이다. 이 단추는 finish() 함수를 호출하여 Android 활동을 종료시키는 콜백을 호출한다.

개발 중인 많은 애플리케이션과 마찬가지로 이 Android 애플리케이션에서는 Android에 내장된 로깅 기능을 사용한다. 이 기사에 있는 캡처 화면의 일부는 Eclipse의 DDMS(Dalvik Debug Monitor Service) 뷰를 캡처한 것이며 이 뷰에서는 LogCat 창을 볼 수 있다. Android 개발 도구를 사용하는 방법과 관련된 자세한 정보는 참고자료에 있는 링크를 참고하기 바란다.

이제는 애플리케이션의 기능에 대한 설명 대신 사용자 인터페이스가 어떻게 구성되는지 살펴보도록 하자.


사용자 인터페이스 설정

이 애플리케이션의 사용자 인터페이스를 작성하는 과정에는 이전에 소개한 세 가지 파일이 관련되어 있다. 먼저, Listing 1에 있는 main.xml 레이아웃 파일을 살펴보도록 하자.


Listing 1. 사용자 인터페이스 레이아웃 파일 main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView android:layout_width="fill_parent"  
android:layout_height="wrap_content" android:text="@string/title" />
    <EditText android:id="@+id/formula" android:layout_width="fill_parent" 
android:layout_height="wrap_content" android:text="" android:visible="False" />
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        <Button android:text="Simple" android:id="@+id/btnSimple" 
android:layout_width="wrap_content" android:layout_height="wrap_content">
</Button>
        <Button android:text="Complex" android:id="@+id/btnComplex"
 android:layout_width="wrap_content" android:layout_height="wrap_content">
</Button>
        <Button android:text="Make Red" android:id="@+id/btnRed" 
android:layout_width="wrap_content" android:layout_height="wrap_content">
</Button>    
    </LinearLayout>
    <WebView android:layout_width="fill_parent" android:layout_height="fill_parent"
 android:id="@+id/calculator" android:layout_weight="1" />
</LinearLayout>

Listing 1의 레이아웃에는 다양한 사용자 인터페이스 요소가 포함되어 있다. android:id 속성이 있으면 애플리케이션이 레이아웃 내에 있는 특정 위젯을 참조할 수 있게 된다. 예를 들면, WebView에는 calculatorid가 포함되어 있지만, id 값은 애플리케이션의 수명 전체에서 변경되지 않기 때문에 TextView에는 id가 없다.

AndroidJSON.java에 있는 onCreate() 메소드는 Listing 2에 있는 것과 같은 레이아웃을 전개하는 기능을 담당한다.


Listing 2. 사용자 인터페이스 설정

public class AndroidJSON extends Activity {
    private final String tag = "AndroidJSON";
    private WebView browser = null;
    private int flipflop = 0;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


        final EditText formula = (EditText) this.findViewById(R.id.formula);
        final Button btnSimple = (Button) this.findViewById(R.id.btnSimple);
        final Button btnComplex = (Button) this.findViewById(R.id.btnComplex);
        final Button btnRed = (Button) this.findViewById(R.id.btnRed);
    // remaining code removed for brevity - shown in next listings
}

여기서는 setContentView() 메소드를 호출하여 레이아웃을 전개한다. 또한, findViewById() 메소드를 호출하여 사용자 인터페이스 요소를 설정한다. main.xml 파일이 저장될 때마다 R.java 파일이 자동으로 생성된다. android:id 속성이 포함된 레이아웃 요소는 Listing 3에 있는 R.id 클래스의 값이 된다.


Listing 3. R.java

/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */

package com.msi.androidjson;

public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int btnComplex=0x7f050002;
        public static final int btnRed=0x7f050003;
        public static final int btnSimple=0x7f050001;
        public static final int calculator=0x7f050004;
        public static final int formula=0x7f050000;
    }
    public static final class layout {
        public static final int main=0x7f030000;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int title=0x7f040000;
    }
}

이 기사의 뒷 부분에서 Button 설정 코드를 다시 살펴보겠지만 지금은 WebView 제어나 위젯을 설정하는 방법에 초점을 맞추도록 하자. Button과 기타 사용자 인터페이스 요소는 간단한 반면에 WebView는 더욱 많은 작업을 필요로 한다. 그렇지만 걱정할 필요는 없다. 그렇게 어렵지 않으며 특히, 잘라내어 붙여넣기 같은 유효성이 증명된 기술을 적용하면 더욱 그렇다. Listing 4에 있는 스니펫을 살펴보자. 이 스니펫은 AndroidJSON.java에 있는 onCreate() 메소드에서 가져온 것이다.


Listing 4. WebView 위젯 설정

        // connect to our browser so we can manipulate it
        browser = (WebView) findViewById(R.id.calculator);

        // set a webview client to override the default functionality
        browser.setWebViewClient(new wvClient());

        // get settings so we can config our WebView instance
        WebSettings settings = browser.getSettings();

        // JavaScript?  Of course!
        settings.setJavaScriptEnabled(true);

        // clear cache
        browser.clearCache(true);

        // this is necessary for "alert()" to work
        browser.setWebChromeClient(new WebChromeClient());

        // add our custom functionality to the javascript environment
        browser.addJavascriptInterface(new CalculatorHandler(), "calc");

        // uncomment this if you want to use the webview as an invisible calculator!
        //browser.setVisibility(View.INVISIBLE);

        // load a page to get things started
        browser.loadUrl("file:///android_asset/index.html");

        // allows the control to receive focus
        // on some versions of Android the webview doesn't handle input focus properly
        // this seems to make things work with Android 2.1, but not 2.2
       // browser.requestFocusFromTouch();

Listing 4에서는 WebView 제어에 해당하는 범위 지정 변수 browser를 Activity에 연결했다. WebView는 세밀하게 사용자 정의할 수 있는 매우 복잡한 클래스이다. 다시 말해서 웹 브라우저와 연관된 기대 함수를 얻기 위해서는 두 개의 클래스를 설정해야 한다. 이러한 작업은 일부 유용한 함수를 얻기 위해 프로그래머가 최소한 수행해야 하는 과정 중 하나이다. 그러나 사용자 정의 수준에는 아무런 제한이 없다. 이 애플리케이션의 목적상 WebView 제어는 최소한으로 배치된다.

WebViewClient는 페이지 로드 시작 및 종료, 양식 재제출, 키보드 인터셉션과 같은 이벤트와 프로그래머가 찾아서 처리해야 할 기타 다양한 이벤트를 캡처할 수 있는 수단을 제공한다. 마찬가지로 매우 유용한 함수인 alert() Javascript 함수를 허용하기 위해 WebChromeClient 인스턴스가 필요하다. 여기에서는 WebView 제어에서 Javascript를 사용하기 위해 WebSettings 클래스를 사용한다.

WebView 제어가 페이지를 탐색하도록 하기 위해 선택할 수 있는 옵션은 두 가지가 있다. 이 애플리케이션에서는 loadurl() 메소드를 프로젝트 자산으로 패키지된 index.html 파일의 완전한 경로와 함께 사용한다. WebView 제어의 설정과 관련된 자세한 정보는 android.webkit 패키지 온라인 문서를 참고한다(참고자료 확인). index.html 파일은 애플리케이션과 함께 제공된 자원에서 WebView 제어로 직접 로드된다. 그림 2의 자원 아래에는 assets 폴더가 있다. 이 폴더는 하이브리드 애플리케이션에서 사용할 html 파일을 저장하기에 적합한 위치이다. (그림 2의 텍스트 전용 버전 보기)


그림 2. Eclipse에 표시된 프로젝트
Eclipse에 표시된 프로젝트

논란의 여지가 있지만 WebView를 다루는 데 있어 가장 중요하고 흥미로운 부분은 WebView의 Javascript 환경을 Android Activity 코드에 연결하는 과정으로 이 부분은 다음 단계에서 살펴본다.


Javascript 인터페이스 연결

다음 단계에서는 WebView에서 관리하는 HTML 파일에 있는 Javascript 코드와 Activity 내에 있는 Java 코드가 상호작용할 수 있게 하는 방법을 살펴본다. 이 과정은 Listing 4에 있는 addJavascriptInterface() 메소드를 호출하여 수행할 수 있다.

이 함수는 Java 클래스 인스턴스와 네임스페이스 ID를 인자로 받는다. 예를 들면, 이 애플리케이션에서는 calc의 네임스페이스를 정의하고 Listing 5에 있는 CalculatorHandler 클래스에서 해당 코드를 구현한다.


Listing 5. CalculatorHandler 구현

// Javascript handler
    final class CalculatorHandler
    {
        private int iterations = 0;
        // write to LogCat (Info)
        public void Info(String str) {
            iterations++;
            Log.i("Calc",str);
        }
        // write to LogCat (Error)
        public void Error(String str) {
            iterations++;
            Log.e("Calc",str);
        } 
        // sample to retrieve a custom - written function with the details provided 
        // by the Android native application code
        public String GetSomeFunction()
        {
            iterations++;
            return "var q = 6;function dynamicFunc(v) { return v + q; }";
        }
        // Kill the app        
        public void EndApp() {
            iterations++;
            finish();
        }
        public void setAnswer(String a)
        {
            iterations++;
            Log.i(tag,"Answer [" + a + "]");
        }
        public int getIterations()
        {
            return iterations;
        }
        public void SendHistory(String s)
        {
            Log.i("Calc","SendHistory" + s);
            try {
                JSONArray ja = new JSONArray(s);
                for (int i=0;i<ja.length();i++) {
                    Log.i("Calc","History entry #" + (i+1) + " is [" + ja.getString(i) 
+ "]");
                }
            } catch (Exception ee) {
                Log.e("Calc",ee.getMessage());
            }
        }
    }

Javascript 환경에서는 window.calc.methodname 구문을 통해 CalculatorHandler의 메소드를 액세스한다. 예를 들면, CalculatorHandlerInfo() 메소드를 구현하며 이 메소드는 문자열 인수를 받아서 애플리케이션 로그에 쓴다. Javascript 환경에서 이 메소드를 액세스하려면 다음과 같은 구문을 사용한다. window.calc.Info("write this string to the application log!") ;.

Javascript 코드에서 Java 코드를 호출하는 기본적인 방법을 이해한 상태에서 Listing 6에 있는 index.html 파일을 시험하여 다양한 메소드를 호출하는 방법을 확인한다.


Listing 6. WebView 제어에서 렌더링하고 실행한 index.html 파일

<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=0.25,
    user-scalable=yes" />
<title>Android to JavaScript with JSON</title>
</head>
<script language="JavaScript">
var cmdHistory = new Array();
function startup() {
    try {
        window.calc.Info("Starting up....");
        cmdHistory[cmdHistory.length] = "startup";
    } catch (ee) {

    }
}
function PerformSimpleCalculation(formula) {
    try {
        cmdHistory[cmdHistory.length] = "PerformSimpleCalculation";
        var answer = eval(String(formula));
        document.getElementById('data').value = answer;
        window.calc.setAnswer(answer);
    }    catch (ee)     {
        window.calc.Error(ee);
    }
}
function PerformComplexCalculation(andmethod) {
    try    {
        /*
         * argument to this function is a single object with 2 "members or properties"
         * operation: this is a string naming what we want the function to do.
         * array of arguments: this is an array of integers
         * 
         */
        //alert(andmethod.operation);
        //alert(andmethod.arguments.length);
        if (andmethod.operation == "addarray") {
            cmdHistory[cmdHistory.length] = "PerformCompleCalculation-addarray";
            var i;
            var result = 0;
            for (i=0;i<andmethod.arguments.length;i++) {
                result += andmethod.arguments[i];
            }
            document.getElementById('data').value = result;
            window.calc.setAnswer(result);
        }
        if (andmethod.operation == "multarray") {
            cmdHistory[cmdHistory.length] = "PerformCompleCalculation-multarray";
            var i;
            var result = 1;
            for (i=0;i<andmethod.arguments.length;i++) {
                result *= andmethod.arguments[i];
            }
            document.getElementById('data').value = result;
            window.calc.setAnswer(result);            
        }
    }    catch (ee)    {
        window.calc.Error(ee);
    }
}
function dynamicfunction()
{
    try {
        cmdHistory[cmdHistory.length] = "PerformCompleCalculation-dynamic";
        eval(String(window.calc.GetSomeFunction()));
        var result = dynamicFunc(parseInt(document.getElementById('data').value));
        document.getElementById('data').value = result;
    }catch (ee) {
        alert(ee);
    }
}
</script>
<body >
<center>
<h3>Running in Web View :)</h3>
this is some sample text here <br />
<input type="text" id="data" value="starting value"><br />
<button onclick="window.calc.Info(document.getElementById('data').value);">Log
 Info</button>&nbsp;&nbsp;
<button onclick="window.calc.Error(document.getElementById('data').value);">Log
 Error</button><br />
<button onclick="dynamicfunction();">Dynamic</button>
<button onclick="alert(String(window.calc.getIterations()));">How 
    Many Calls</button>
<button onclick="window.calc.SendHistory(JSON.stringify(cmdHistory));">
    History</button>
<button onclick="if (window.confirm('End App?')) window.calc.EndApp();">Kill This
 App</button><br />
</center>
</body>
</html>

Listing 6의 마지막 부분을 대상으로 Button 핸들러를 시험한다. 본질적으로 이 부분에서는 window.calc 네임스페이스에 있는 메소드를 호출하며 이 메소드는 AndroidJSON.java 파일에 있는 CalculatorHandler 클래스에서 구현된다.

Listing 5Listing 6를 같이 살펴보면 코드 상호작용이 Javascript 환경에서 시작하여 Java 소스 파일에서 구현된다는 사실을 확인할 수 있다. 그러나 WebView에서 수행되기를 원하는 몇 가지 조치를 Activity 코드에서 시작하면 어떨까?

이제 Java 코드를 자세히 살펴보자.


Javascript 코드 삽입

Javascript 코드에 수학 공식을 전달하여 평가하는 작업을 먼저 살펴보도록 하자. Javascript의 기능 중 유용하지만 위험한 기능 중의 하나는 eval() 함수이다. eval() 함수에서는 코드 문자열을 런타임 시에 평가할 수 있다. 다음 예제에서는 EditText 제어에서 문자열을 받아서 Javascript 환경에 전달하여 평가한다. 특히, Listing 6에 있는 PerformSimpleCalculation() 함수를 호출한다.

Listing 7에는 AndroidJSON.java에서 가져온 코드가 포함되어 있으며 이 코드는 단추 선택을 처리하는 기능을 담당한다.


Listing 7. Java에서 PerformSimpleCalculation() Javascript 함수 호출

  btnSimple.setOnClickListener(new OnClickListener()
  {
       public void onClick(View v) {
         Log.i(tag,"onClick Simple");
         // Perform action on click
         try
         {
            String formulaText =  formula.getText().toString();
            Log.i(tag,"Formula is [" + formulaText + "]" );
            browser.loadUrl("javascript:PerformSimpleCalculation(" + formulaText + ");");
         }
         catch (Exception e)
         {
               Log.e(tag,"Error ..." + e.getMessage());
         }
       }
  });

이 메소드는 여러 행으로 구성되어 있지만 여기서 중요한 행은 browser.loadurl() 메소드가 있는 행으로 이 메소드는 javascript:<code to execute> 형식의 문자열을 전달한다.

이 Javascript 코드는 WebView의 현재 페이지에 삽입되어 실행된다. WebView에서 정의한 Javascript 코드를 이러한 방식으로 Java 코드에서 실행할 수 있다.

Simple 예제에서는 문자열을 전달한다. 그러나 더욱 복잡한 구조를 처리해야 하는 경우에는 어떻게 해야 하나? 이러한 경우에는 JSON을 사용하면 도움이 된다. Listing 8에는 Listing 6에 있는 PerformComplexCalculation() 함수를 호출하는 과정이 표시되어 있다.


Listing 8. JSON 오브젝트를 전달하여 더욱 복잡한 함수 호출하기

btnComplex.setOnClickListener(new OnClickListener()
{
     public void onClick(View v) {
         Log.i(tag,"onClick Complex");
         // Perform action on click
         try
         {
             String jsonText = "";
         
             if (flipflop == 0)
             {     
                 jsonText = "{ \"operation\" : \"addarray\",\"arguments\" :
 [1,2,3,4,5,6,7,8,9,10]}";
                 flipflop = 1;
             } else {
                 jsonText = "{ \"operation\" : \"multarray\",\"arguments\" :
 [1,2,3,4,5,6,7,8,9,10]}";
                 flipflop = 0;
             }
             Log.i(tag,"jsonText is [" + jsonText + "]" );
             browser.loadUrl("javascript:PerformComplexCalculation(" + jsonText + ");");
         }
         catch (Exception e)
         {
             Log.e(tag,"Error ..." + e.getMessage());
         }
         
     }
});

Listing 6에 있는 PerformComplexCalculation Javascript 함수를 살펴보자. 전달된 인수는 문자열이 아니라 직접 작성한 오브젝트이다.

  • operation - 처리할 프로시저나 함수의 이름
  • arguments - 정수 배열

이 오브젝트에는 두 가지 특성만 있지만 더욱 다양한 요구사항을 충족시키기 위해 임의로 오브젝트를 더 복잡하게 할 수 있다. 이 예제에서 PerformComplexCalculation() Javascript 함수는 서로 다른 두 개의 조작 즉, addarray와 multarray를 지원한다. 이러한 조작을 통해 호출 작업이 완료되면 window.calc.setAnswer 함수를 호출하여 결과를 Java 코드로 돌려보낸다. 여기서 Java 코드와 Javascript 코드 간의 양방향 데이터 플로우를 확인할 수 있다.

이 예제에서는 JSON 오브젝트를 전달하지만 경험에 따르면 Java 코드로 되돌아온 Java 문자열을 처리할 때는 이 문자열을 Javascript 문자열로 변환하는 것이 도움이 된다. 이러한 작업은 다음 예제에서와 같이 String 함수에 값을 전달하여 수행할 수 있다. eval(String(formula));

eval() Javascript 함수는 Javascript 문자열을 사용한다. 변환을 하지 않으면 eval 함수는 기본적으로 아무런 작업도 수행하지 않는다.

조금 더 복잡한 예제에서는 WebView에서 Dynamic 단추를 선택했을 때의 코드 시퀀스를 자세히 살펴보기 바란다.

문자열 배열을 Javascript 환경에서 Java 환경으로 전달하는 과정을 살펴보는 것으로 코드 예제를 마무리하기로 하자.


JSON 오브젝트 교환하기

예제 애플리케이션(index.html)에 있는 Javascript 코드는 로컬 함수 호출을 cmdHistory 페이지 레벨 배열에 기록한다. 함수가 호출될 때마다 이 배열에 새로운 항목이 추가된다. 예를 들어, dynamicfunction() 함수가 호출되면 다음과 같이 새로운 문자열이 저장된다. cmdHistory[cmdHistory.length] = "PerformCompleCalculation-dynamic";

이 방식은 페이지 레벨에서 사용 데이터를 수집하는 간단한 예제로 이 방식과 관련해서 특별히 고려해야 할 사항은 없다. 이 데이터는 유용하게 사용될 수 있으며 Android 애플리케이션의 데이터베이스에 저장된다. 이 데이터를 Java 코드로 불러오려면 어떻게 해야 할까?

문자열 오브젝트의 배열을 전송하려면 인수로 배열을 전달하는 JSON.stringify 함수를 호출해야 한다. JSON.stringify 함수에서는 복잡한 오브젝트의 특성을 형식화하는 방법을 선택적으로 사용자 정의할 수 있다. 이러한 작업을 수행하는 방법과 관련된 자세한 정보는 json.org에 있는 설명을 참조하기 바란다(참고자료 확인).

그림 3에는 애플리케이션을 실행하여 JSON 배열을 구문 분석한 후 로그에 기록한 내용이 표시되어 있다.


그림 3. Javascript에서 전송된 JSON 배열 구문 분석하기
Javascript에서 전송된 JSON 배열을 구문 분석한 내용의 화면 캡처

이 예제는 문자열 데이터만 저장하므로 문자열 데이터를 더 긴 문자열에 간단히 추가하고 CalculatorHandler에서 간단한 함수를 호출하여 이 문자열을 구문 분석할 수 있다. 그러나 애플리케이션에서 특정 변수값과 같은 다른 데이터를 추적하거나 특정 함수의 호출 기간을 기록하여 코드의 특성을 분석할 경우에는 어떻게 할 것인가? 더욱 복잡한 시나리오에서는 오브젝트를 기록하고 교환하는 기능이 확실히 중요하다.


요약

이 기사에서는 WebKit을 활용하는 하이브리드 애플리케이션과 관련된 일반적인 주제뿐만 아니라 Android 애플리케이션의 Java 코드와 WebView의 Javascript 코드 간에 데이터를 전송하는 기술을 살펴보았다. 하이브리드 애플리케이션에는 상상할 수 있는 모든 요소 중에서 유연하고 우수한 모바일 애플리케이션을 전달하는 데 필요한 가장 중요한 요소와 Javascript, JSON, 콜백 함수 및 Android-SDK Java 코드가 함께 결합되어 있다.



다운로드 하십시오

설명이름크기다운로드 방식
Article source codeandjson.zip58KBHTTP

다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술 얻기

  • Android SDK: Android SDK를 다운로드하여 API 참조를 액세스하고 공식 Android 개발자 사이트에서 Android와 관련된 최신 뉴스를 얻자. 이 기사에 있는 예제를 실습하기 위해서는 버전 1.5 이상이 필요하다.

  • Eclipse: 최신 Eclipse IDE를 다운로드하자.

  • Android Open Source Project: Android는 오픈 소프이다. 따라서 여기에서 소스 코드를 얻을 수 있다.

  • JSONLint: 이 온라인 JSON 유효성 검증기를 사용해보자.

  • IBM 제품 평가판을 다운로드하거나 IBM SOA Sandbox의 온라인 시험판을 살펴보고 DB2®, Lotus®, Rational®, Tivoli® 및 WebSphere®의 애플리케이션 개발 도구 및 미들웨어 제품을 사용해 볼 수 있다.

토론

필자소개

대학에서 야구 선수로 활동한 후 L.A. Lakers와의 다년 계약을 맺지 못한 Frank Ableson은 컴퓨터 소프트웨어 설계로 관심을 돌렸다. 복잡한 문제 해결을 좋아하는 그는 특히 통신 및 하드웨어 인터페이스 분야에 많은 관심을 가지고 있다. 부인인 Nikki와 자녀들과 함께 여가 시간을 보내는 단란한 가정의 가장이기도 하다. 그의 이메일 주소는 frank@cfgsolutions.com이다.

잘못된 도움말 신고

부정사용 신고

감사합니다. 이 항목은 운영자가 관심을 표시했습니다.


잘못된 도움말 신고

부정사용 신고

제출실패 신고. 나중에 다시 실행해주세요.


디벨로퍼웍스 로그인


IBM ID가 필요하세요?
IBM ID를 잊으셨습니까?


비밀번호를 잊으셨습니까?
비밀번호 변경

developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


developerWorks에 처음 로그인하면 developerWorks프로파일이 생성됩니다.귀하의 프로파일에서 동의하신 내용이 공개되지만 이 사항은 언제든지 변경 가능합니다. 귀하의 성명(숨김으로 체크되어 있어도 표시됩니다)과 디스플레이 이름은 게시한 컨텐츠나 사이트 엑세스시 표시됩니다.

화면상에 보여지는 닉네임을 정하세요.

처음 developerWorks에 로그인할 때 프로파일이 작성되므로, 이를 위해 디스플레이 이름을 선택해야 합니다. 선택하신 디스플레이 이름은 developerWorks에 게시한 컨텐츠에 표시됩니다.

3글자 이상 31글자 이하의 길이로 사용 가능합니다. dW커뮤니티 내에서는 보안상 이메일주소를 제외한 다른 이름을 지정하셔야 합니다.

3개의 &이나 대쉬를 포함해주시고 31글자내로 제한해주세요.


developerWorks 이용 약관에 동의하시는 경우 제출을 클릭하십시오. 이용 약관.

 


아티클 순위

의견

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=20
Zone=XML, 웹 개발
ArticleID=593690
ArticleTitle=Android에서 XML과 JSON 사용하기, Part 2: JSON을 사용하여 하이브리드 Android 애플리케이션 전달하기
publish-date=08242010
author1-email=frank@cfgsolutions.com
author1-email-cc=

태그

Help
검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오.

태그를 더 많이 보거나 적게 보기 위해 슬라이더 막대를 사용하십시오.

인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다.

내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.

검색 필드를 사용하여 My developerWorks 내에서 해당 태그가 사용된 모든 종류의 컨텐츠를 검색하십시오. 인기 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 최고 인기 태그를 보여줍니다. 내 태그는 특정 컨텐츠 존(예를 들어, 자바, 리눅스, WebSphere)의 귀하의 태그를 보여줍니다.