목차

배경

전자정부 서비스 제공 시 모바일 디바이스의 고유 기능의 호출을 위한 모바일 하이브리드 어플리케이션 개발을 지원하기 표준프레임워크 모바일 디바이스 API 실행환경을 개발 및 배포하였으며, 그에 따라 모바일 하이브리드 앱 표준프레임워크 구축환경을 효과적으로 확산, 보급하기 위해 개발자가 손쉽게 접근할 수 있는 모바일 디바이스 API의 활용예제인 모바일 디바이스 API 가이드프로그램을 제공하게 되었다.

목적

모바일 하이브리드 앱 형태로 만들어진 표준프레임워크 모바일 디바이스 API의 설치 및 활용을 효과적으로 전달하기 위해 사용자의 수준 및 사용환경에 적합한 내용의 모바일 디바이스 API 예제를 구성하여, 개발 생산성 및 응용프로그램 품질 제고, 표준화 촉진등의 효과를 가져 올 수 있다.

준수 지침

전자정부 웹 호환성 준수지침

1) 근거 기준: 행정안전부 고시 “제 2010-40호

2) 개정 이유: 모바일 전자정부 서비스 제공시 접근성 제고등을 위하여 공공기관이 준수해야 할 사항을 규정

3) 주요 개정 내용:

4) 전자정부 모바일 서비스 제공 원칙

5) 모바일 ‘웹’ 과 ‘앱’ 서비스의 구현 방법 차이

모바일 애플리케이션 접근성 지침

1) 근거 기준: 행정안전부 고시 “제 2011-38호

2) 개정 이유: 모바일 전자정부 서비스 제공시 접근성 제고등을 위하여 공공기관이 준수해야 할 사항을 규정

3) 주요 내용:

4) 모바일 애플리케이션 접근성 준수를 위한 개발절차

구성 내용

iOS, Android 플랫폼 두 종의 디바이스 API 가이드 프로그램을 각 샘플 템플릿 프로그램 및 디바이스 API 별로 가이드 프로그램을 구현하여 제공한다..

* 디바이스 API 가이드프로그램의 종류

디바이스 API 구현개요
SampleTemplate 폰갭에서 제공하는 디바이스API 10가지를 하이브리드 앱으로 구현하여 샘플을 제공한다.
Contact 현재 저장된 전화번호부를 리스트 형태로 보여주며 찾기 기능을 통해 전화번호부를 검색 및 서버에 연락처를 백업한다.
GPS 지도서비스와 연계 하여 지도화면 위에 현재좌표와 위치를 표시한다.
Accelerator 디바이스의 가속도 정보를 조회하여 이미지의 움직임으로 화면에 표시한다.
Camera 카메라 기능을 통해 사진을 촬영하며 촬영된 사진을 서버에 업로드 및 섬네일 형태로 조회한다.
Vibrator 알람 방식 선택 기능을 제공하며 타임설정을 통해 사용자 알람을 동작한다.
Compass 디바이스가 가리키는 방향 정보를 이용하여 지도화면의 방향 정보를 실시간으로 변경한다.
Media 서버에 위치한 미디어 파일 목록을 확인하고 선택한 미디어 파일을 재생, 정지, 앞으로 탐색, 뒤로 탐색 버튼을 통해 컨트롤 할 수 있는 기능을 제공한다.
File 동영상 캡쳐 기능을 통해 촬영된 파일을 디바이스에 저장, 조회하며 파일을 서버에 업로드/다운로드 한다.
Device 디바이스 메타데이터를 조회하여 그리드 형태로 사용자에게 제공한다.
Network 디바이스 네트워크 정보를 조회하여 사용자 화면에 표시한다.
NPKI 모바일용 GPKI인증서를 이용한 인증을 수행하며 로그인 로그정보를 서버에 저장한다.
Interface 사용자 정보를 서버에 저장하는 회원가입 기능을 제공하며 가입된 정보로 로그인 할 수 있는 기능을 제공한다.

모바일 디바이스 API 가이드 프로그램 아키텍처

iOS 하이브리드 어플리케이션 프로젝트 구조

이름 설명
CordovaLib.xcodeproj 폰갭을 사용하기 위한 폰갭 Sub 프로젝트
Framework SystemConfiguration.framework 시스템 영역 접근 framework,
CFNetwork.framework 네트워크 영역 접근 framework, MobileCoreService.framework 디바이스 Core 영역 접근 framework
www index.html, *.css, *.js 파일., App의 첫 페이지 index.html와 디자인 관련된 css, PhoneGap 및 JavaScript js 구성.
Design 디바이스 배경에 쓰이는 icons 파일의 폴더, App 실행 시 보여줄 splash 파일의 폴더
Plugins 추가 Plug-in 폴더, config.XML에 추가된 Plug-in 정보 기록, CDVPlugin 클래스를 상속
이름 설명
Reachability 애플에서 무료 제공하기 때문에 라이선스 없음,
현재 디바이스의 3G 또는 wi-fi 아니면 네트워크 미연결 mode 체크,
3G 또는 wi-fi 아니면 네트워크 미연결 변경 시 알림 제공
ASIHTTPRequest BSD License, GET/POST/PUT/DELETE 방식 지원,
HTTP, HTTPS 통신 지원,
파일 업로드/다운로드 지원 및 진행 % 상태 알림 제공,
동기 및 비동기 통신 지원, 통신 시작, 실패, 성공 상태 알림 제공
PhoneGap 모바일 웹 페이지에서 디바이스에 직접 접근 가능
이름 설명
CordovaLib.xcodeproj 폰갭 Command Line Interface를 사용하여 프로젝트를 생성해야한다.
Framework 프로젝트 설정 화면에서 SystemConfiguration framework, CFNetwork framework, MobileCoreService framework 를 추가한다.
www UIWebView에서 보여줄 첫 페이지 index.html 파일,
디자인에 관련된 css 파일, PhoneGap 및 JavaScript의 js 파일이 위치한다.
Design icons 폴더에는 디바이스 바탕화면에 보일 Icon.png, Icon@2x.png, Icon-72.png 파일이 위치한다,
splash 폴더에는 앱 실행이 보여줄 splash화면 이미지 Default.png, Default@2x.png가 위치한다.
Plugins Plug-in을 추가 생성하고자 할 경우 CDVPlugin 클래스를 상속받아서 여기에 추가한다,
추가된 Plug-in은 config.xml 파일의 <feature> 엘리먼트 추가

Android 하이브리드 어플리케이션 프로젝트 구조

리소스 위치 설명
AndroidManifest.xml/AndroidManifest.xml안드로이드 어플리케이션 디스크립터 파일로 액티비티, 컨텐츠프로바이더, 서비스, 어플리케이션에서 사용되는 수신자들을 정의한다. 권한 설정도 가능하다.
Activity.javasrc/패키지명/*Activity.java안드로이드 어플리케이션을 구성하는 가장 기본이 되는 빌딩 블록으로 보통의 경우 한 화면을 차지하면서 뷰로 구성된 유저 인터페이스를 화면에 표시하고 사용자의 입력을 처리하는 역할을 한다
R.javagen/패키지명/R.java안드로이드에서 사용되는 리소스를 관리하는 자바 파일로 리소스에 대한 참조 값이 정의 된다. 자동으로 SDK에 의해 생성 되며 사용자가 수정하지 못하도록 되어있다.
HTML/JS/CSS/Imageassets/www/하이브리드 어플리케이션의 주요 구성요소로 화면 요소 및 비즈니스 로직을 포함한다.
Phonegap-x.x.jarlib/디바이스 API인 폰갭 프레임워크의 안드로이드 플랫폼의 네이티브와 통신하기 위한 라이브러리이다.
Android.jarAndroid-sdk/platforms/android-version/안드로이드 플랫폼에서 API와 관련되 라이브러리 파일이다.안드로이드 버전에 따라 파일이 달라진다.
Icon.pngres/drawable-dpi/어플리케이션이 설치 되었을 때 사용자가 볼 수 있는 아이콘
Main.xmlres/layout/main.xml안드로이드 플랫폼에서 사용되는 화면 UI를 xml로 정의해 놓은 파일
Strings.xmlres/values/strings.xml안드로이드 플랫폼에서 사용되는 문자열을 관리하는 xml 파일로 다국어를 지원하는 용도로 사용 할 수 있다.
config.xmlres/xml/plugins.xml폰갭 프레임워크에 등록된 플러그인이 정의되는 파일로 폰갭의 디바이스 API들이 플러그인 형태로 등록 되어 있다.

Phonegap 프로젝트인 경우 일반적인 APP 구현 방식과는 다르게 Phonegap 에서 제공하는 Class(DroidGap) 을 상속하여 메인 클래스를 구현하며. Phonegap 에서 하이브리드 앱 구현을 위해 미리 Webkit 을 상속받아 구현해 놓은 onCreate 및 loadUrl을 호출하여 웹 리소스(HTML, CSS, JavaScript)들을 Webview 로 주입하여 렌더링 한다. 기본적으로 폰갭은 디폴트로 Rich 클라이언트 방식을 제공하며, 프로젝트 내에있는 Index.html을 최초 호출하도록 되어 있다.

package kr.go.egovframework.hyb.example;

import org.apache.cordova.*;

import android.os.Bundle;

/**  
 * @Class Name : example_AndroidActivity.java
 * @Description : example_AndroidActivity Class
 * @Modification Information  
 * @
 * @  수정일       수정자                 수정내용
 * @ ---------   ---------   -------------------------------
 * @ 
 * 
 *  Copyright (C) by MOPAS All right reserved.
 */
public class Example_AndroidActivity extends DroidGap
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);        
        // Clear cache if you want
        super.clearCache();
        //super.appView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
        super.loadUrl("file:///android_asset/www/index.html");
    }
}

폰갭 API 및 자바스크립트를 이용한 어플리케이션 주요 로직을 구현한다.



<!DOCTYPE html>
<html LANG="ko"> 
<!-- 
  /**
  * @Class Name : index.html
  * @Description : 가이드 프로그램 표준코드 index 화면
  * @Modification Information
  * 
  *   수정일         수정자                   수정내용
  *  -------    --------    ---------------------------
  *  
  *
  *  
  * Copyright (C) 2009 by MOPAS  All right reserved.
  */
 -->
<head> 
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>example API Guide</title>
    
    <!-- Phonegap.js import -->
    <script type="text/javascript" charset="utf-8" src="js/egovframework/mbl/cmm/cordova.js"></script>
    
    <!-- eGovFrame Common import -->        
    <link rel="stylesheet" href="css/egovframework/mbl/cmm/jquery.mobile-1.3.2.css" />
    <link rel="stylesheet" href="css/egovframework/mbl/cmm/theme-1.1.1.css" />
    <link rel="stylesheet" href="css/egovframework/mbl/cmm/EgovMobile-1.3.2.css" />
    
    <script type="text/javascript" src="js/egovframework/mbl/cmm/jquery-1.9.1.min.js"></script>
    <script>
            $(document).on("pageinit", function(){
                             $.mobile.defaultPageTransition = 'none';
                             });
    </script>
    <script type="text/javascript" src="js/egovframework/mbl/cmm/jquery.mobile-1.3.2.min.js"></script>
    <script type="text/javascript" src="js/egovframework/mbl/cmm/modernizr-2.0.4.js"></script>
    <script type="text/javascript" src="js/egovframework/mbl/cmm/EgovMobile-1.3.2.js"></script>
    <script type="text/javascript" src="js/egovframework/mbl/cmm/EgovHybrid.js"></script>

    <script type="text/javascript" src="js/egovframework/mbl/cmm/jquery.validate.min.js"></script>
    <script type="text/javascript" src="js/egovframework/mbl/cmm/json2.js"></script>

	<!-- iScroll.js import -->
    <script type="text/javascript" src="js/iscroll/iscroll.js"></script>

    <script type="text/javascript" charset="utf-8">

	</script>      
   
</head>
	
<body>

	<div id="intro" data-role="page">
		Device API Guide Android 1.9
	</div>

</body>
</html>



Manifest.xml은 모바일 어플리케이션 설정 파일로서 어플리케이션의 설정 및 필요한 기능, 권한등을 정의한다.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kr.go.egovframework.hyb.example"
    android:versionCode="1"
    android:versionName="1.0" >
    
	<supports-screens
		android:largeScreens="true"
		android:normalScreens="true"
		android:smallScreens="true"
		android:resizeable="true"
		android:anyDensity="true"
		/>

	<uses-permission android:name="android.permission.CAMERA" />
	<uses-permission android:name="android.permission.VIBRATE" />
	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
	<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
	<uses-permission android:name="android.permission.READ_PHONE_STATE" />
	<uses-permission android:name="android.permission.INTERNET" />
	<uses-permission android:name="android.permission.RECEIVE_SMS" />
	<uses-permission android:name="android.permission.RECORD_AUDIO" />
	<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
	<uses-permission android:name="android.permission.READ_CONTACTS" />
	<uses-permission android:name="android.permission.WRITE_CONTACTS" />
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
	<uses-permission android:name="android.permission.GET_ACCOUNTS" />
	<uses-permission android:name="android.permission.BROADCAST_STICKY" />
	
	<uses-permission android:name="android.permission.READ_PHONE_STATE" />

 	<uses-feature android:name="android.hardware.camera" /> 
  	<uses-feature android:name="android.hardware.camera.autofocus" /> 

	<application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:debuggable="true">
		<activity android:name=".Example_AndroidActivity" 
			      android:label="@string/app_name" android:configChanges="orientation|keyboardHidden">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" /> 
				
  				<category android:name="android.intent.category.LAUNCHER" /> 
  			</intent-filter>
  		</activity>
		<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name" 
                  android:configChanges="orientation|keyboardHidden">
  			<intent-filter>
			</intent-filter> 
  		</activity>
  </application>

  <uses-sdk android:minSdkVersion="8" /> 
  </manifest>

<plugin> 태그에는 전자정부 디바이스 API 실행환경의 디바이스 API들이 정의되어 있으며 사용자 플러그인 또한 <plugin> 태그를 이용하여 등록하여야 한다.


<widget xmlns     = "http://www.w3.org/ns/widgets"
        id        = "io.cordova.helloCordova"
        version   = "2.0.0">
    <name>Hello Cordova</name>

    <description>
        A sample Apache Cordova application that responds to the deviceready event.
    </description>

    <author href="http://cordova.io" email="dev@cordova.apache.org">
        Apache Cordova Team
    </author>

    <access origin="*"/>

    <!-- <content src="http://mysite.com/myapp.html" /> for external pages -->
    <content src="index.html" />

    <preference name="loglevel" value="DEBUG" />
    <!--
      <preference name="splashscreen" value="resourceName" />
      <preference name="backgroundColor" value="0xFFF" />
      <preference name="loadUrlTimeoutValue" value="20000" />
      <preference name="InAppBrowserStorageEnabled" value="true" />
      <preference name="disallowOverscroll" value="true" />
    -->

    <feature name="App">
      <param name="android-package" value="org.apache.cordova.App"/>
    </feature>
    <feature name="Geolocation">
      <param name="android-package" value="org.apache.cordova.GeoBroker"/>
    </feature>
    <feature name="Device">
      <param name="android-package" value="org.apache.cordova.Device"/>
    </feature>
    <feature name="Accelerometer">
      <param name="android-package" value="org.apache.cordova.AccelListener"/>
    </feature>
    <feature name="Compass">
      <param name="android-package" value="org.apache.cordova.CompassListener"/>
    </feature>
    <feature name="Media">
      <param name="android-package" value="org.apache.cordova.AudioHandler"/>
    </feature>
    <feature name="Camera">
      <param name="android-package" value="org.apache.cordova.CameraLauncher"/>
    </feature>
    <feature name="Contacts">
      <param name="android-package" value="org.apache.cordova.ContactManager"/>
    </feature>
    <feature name="File">
      <param name="android-package" value="org.apache.cordova.FileUtils"/>
    </feature>
    <feature name="NetworkStatus">
      <param name="android-package" value="org.apache.cordova.NetworkManager"/>
    </feature>
    <feature name="Notification">
      <param name="android-package" value="org.apache.cordova.Notification"/>
    </feature>
    <feature name="Storage">
      <param name="android-package" value="org.apache.cordova.Storage"/>
    </feature>
    <feature name="FileTransfer">
      <param name="android-package" value="org.apache.cordova.FileTransfer"/>
    </feature>
    <feature name="Capture">
      <param name="android-package" value="org.apache.cordova.Capture"/>
    </feature>
    <feature name="Battery">
      <param name="android-package" value="org.apache.cordova.BatteryListener"/>
    </feature>
    <feature name="SplashScreen">
      <param name="android-package" value="org.apache.cordova.SplashScreen"/>
    </feature>
    <feature name="Echo">
      <param name="android-package" value="org.apache.cordova.Echo"/>
    </feature>
    <feature name="Globalization">
      <param name="android-package" value="org.apache.cordova.Globalization"/>
    </feature>
    <feature name="InAppBrowser">
      <param name="android-package" value="org.apache.cordova.InAppBrowser"/>
    </feature>
    <!-- Deprecated plugins element. Remove in 3.0 -->
    <plugins>
    	<plugin name="App" value="org.apache.cordova.App"/>
    	<plugin name="Geolocation" value="org.apache.cordova.GeoBroker"/>
    	<plugin name="Device" value="org.apache.cordova.Device"/>
    	<plugin name="Accelerometer" value="org.apache.cordova.AccelListener"/>
    	<plugin name="Compass" value="org.apache.cordova.CompassListener"/>
    	<plugin name="Media" value="org.apache.cordova.AudioHandler"/>
    	<plugin name="Camera" value="org.apache.cordova.CameraLauncher"/>
    	<plugin name="Contacts" value="org.apache.cordova.ContactManager"/>
    	<plugin name="File" value="org.apache.cordova.FileUtils"/>
    	<plugin name="NetworkStatus" value="org.apache.cordova.NetworkManager"/>
    	<plugin name="Notification" value="org.apache.cordova.Notification"/>
    	<plugin name="Storage" value="org.apache.cordova.Storage"/>
    	<plugin name="Temperature" value="org.apache.cordova.TempListener"/>
    	<plugin name="FileTransfer" value="org.apache.cordova.FileTransfer"/>
    	<plugin name="Capture" value="org.apache.cordova.Capture"/>
    	<plugin name="Battery" value="org.apache.cordova.BatteryListener"/>
    	<plugin name="SplashScreen" value="org.apache.cordova.SplashScreen"/>
    	<plugin name="EgovInterfacePlugin" value="kr.go.egovframework.hyb.plugin.EgovInterfacePlugin" />
		<plugin name="StorageInfoPlugin" value="kr.go.egovframework.hyb.plugin.EgovStorageInfo" />
		<plugin name="DeviceNumberPlugin" value="kr.go.egovframework.hyb.plugin.EgovDeviceNumber" />        
    </plugins>
</widget>