[Android] 외부(오픈소스) 라이브러리 사용하기

Published on: 2013. 11. 14. 16:26 by louis.dev
안드로이드 프로젝트 같은경우에는 github구글 코드 같은 사이트에서 안드로이드용 오픈소스 라이브러리를 많이 볼수 있습니다. 이러한 오픈소스 라이브러리를 안드로이드 프로젝트에서 사용하는 방법을 적어보자 합니다. Step 1. 외부라이브러리를 다운로드 받아 이클립스로 import 합니다. android 3.0에서 부터  Actionbar라는 뷰가 생겼는데요, 하위버전의 안드로이드에서는 Actionbar를 사용할수가 없어 ActionbarSherlock이라는 외부라이브러리를 이용해서 Actionbar를 구현해야 합니다. 해당사이트로 이동하여 라이브러리를 다운 받은 후 압축을 풉니다. 다음으로 이클립스로 돌아와 해당 라이브러리 프로젝트를 import 시켜줍니다.  
일반 적인 경우에는 아래의 스크린샷 처럼 Android -> Existing Android Code Into Workspace 메뉴를 선택하여  import를 시키면 됩니다.  

 그러나 Actionbar Sherlock 라이브러리를 보면 pom.xml이 있는것을 확인할수 있습니다. 즉 해당 라이브러리는 Maven 기반의 프로젝트임을 확인할 수 있습니다. 이렇게 외부 라이브러리가 Maven기반이라면 아래의 사진처럼 Maven -> Existing Maven Project 를 선택하여 Maven 프로젝트를 import 시킵니다. 안드로이드 프로젝트에서 Maven을 사용하려면 이클립스 플러그인이 설치되어야 합니다. 안드로이드-메이븐 개발환경 구축은 "Maven으로 안드로이드 개발환경 구축하기"를 참고하시면 됩니다.

   

 위의 화면에서 Next를 누르면 다음과 같은 화면이 나오는데요.  

실질적으로 필요한 프로젝트는 library이지만 샘플코드도 확인해야 하기 때문에 저는 모든 프로젝트를 import 하겠습니다. Step 2. 외부라이브러리를 현재 개발하려는 프로젝트에 추가 합니다. 추가는 간단합니다. 현재 프로젝트에서 마우스 오른쪽을 클릭하여 properties메뉴로 들어갑니다.

   

 좌측메뉴 중 Android를 선택하면 다음과 같은 화면이 나타나는데요.

   

우측 하단의 Library영역에서 Add를 눌러 라이브러리 프로젝트인 Actionbar Sherlock을 선택합니다.

   

 위의 스크린샷처럼 Library영역에 actionbarsherlock 프로젝트가 라이브러리로 추가된걸 볼 수 있습니다.   이렇게 외부라이브러리를 추가하는 방법을 확인해 보았습니다. 만약 현재 개발중인 프로젝트가 Maven을 사용하고 있다면 위의 작업을 한 뒤 pom.xml의 dependency부분에 apklib 디펜던시를 추가해 주어야 합니다.
<dependencies>
	<dependency>
		<groupId>com.actionbarsherlock</groupId>
		<artifactId>library</artifactId>
		<version>4.2.0</version>
		<type>apklib</type>
	</dependency>
</dependencies>
 

Maven환경에서 개발 시 유의할점

위의 포스팅을 쭉 읽어 오면서 이상한 점이 하나 보일것입니다. Maven환경에서 개발을 많이 해보신 경우라면 좀더 빨리 눈치 채실것 같은데요. 그 이상한 점은 바로 apklib파일을 pom.xml에 dependency로 추가를 했는데도 불구하고 project의 properties 메뉴에서 외부라이브러리를 중복적으로 추가하고 있다는 점입니다. 일반적으로 의존관계의 jar로 패키징된 라이브러리들은 pom.xml에 dependency를 추가만 해주는것만으로도 자연스럽게 디펜던시에 추가가 되어 따로 설정 할일이 없었는데 apklib파일 같은 경우는 왜이렇게 중복적으로 라이브러리를 지정해야 할까요? 그 이유는 Maven프로젝트를 android프로젝트로 인식하는 Android Connector for m2e  플러그인이 apklib를 아직 미지원 하기 때문입니다. 그렇기 때문에 pom.xml에 dependency를 추가했어도 android connector plugin이 apklib를 인식하지 못하기 때문에 외부라이브러리를 찾지 못한다고 이클립스에서 에러를 내뿜게 됩니다. 그렇다고 실제 dependency에 추가가 되지 않은 것은 아니며 단지 이클립스에서 인식을 못하는 것입니다. 그래서 이렇게 에러가 발생하더라도 해당 프로젝트를 maven으로 패키징 하게 되면 문제가 없이 패키징이 되는것을 확인할 수 있습니다. 하지만 개발을 하기 위해서는 이클립스에서 외부라이브러리를 인식시켜 이클립스가 제공해주는 다양한 기능(code assist같은) 을 사용해야 하기 때문에 Properties에서 외부라이브러리를 추가해 주어야 합니다.



[Android] Maven으로 안드로이드 개발환경 구축하기

Published on: 2013. 11. 14. 16:23 by louis.dev
이번에 안드로이드 프로젝트를 진행하면서 자바 웹 개발시에도 많이 사용하는 Maven을 이용해 안드로이드도 개발을 진행하도록 하였습니다. 모든 자바 프로젝트가 그렇듯 세팅에 많은 시간을 들여야 하기 때문에 나중에 혹시 또 안드로이드 프로젝트를 진행할때 참고하려고 히스토리를 남겨 봅니다.

첫번째. Maven을 설치해 줍니다.

당연하겠지만 Maven을 사용하려면 Maven을 설치를 해야겠지요..^^;; Maven은 apache사이트에서 다운로드 받으실수 있습니다. 설치하는 방법은 아주 간단합니다. 다운로드받은 .zip파일을 원하는 곳에 압축을 풀어 놓습니다. 그리고 환경변수로 MAVEN_HOME을 지정해야 하는데 이 MAVEN_HOME은 다운로드 받은 메이븐 파일을 압축풀어 놓은 위치를 MAVEN_HOME으로 지정하면 됩니다. * 참고로 MAVEN-ANDROID-PLUGIN은 MAVEN 3.3이상 MAVEN 3.0.3버전 사용을 요구하고 있습니다. 그러므로 MAVEN을 설치하실때는 꼭 3.0.3이상의 버전을 설치하시기 바랍니다.  

두번째. Android-SDK, 이클립스를 다운받습니다.

예전같은 경우에는 이클립스 따로, Android-SDK 따로 다운받아서 이클립스 플러그인을 설치하는 번거로운 작업을 진행했어야 하는데요, 요즘에는 안드로이드 개발자 사이트에 가면 ADT Bundle을 다운로드 받을 수 있는데 여기에 Android-SDK뿐만 아니라  이클립스가 함께 포함되어있습니다. 이걸 다운로드 받으면 따로 안드로이드 이클립스 플러그인을 다운로드 받지 않아도 되기 때문에 좀더 빠르게 개발환경을 구축할수 있습니다. 여기서 가장 중요한 점은 위에서 환경변수로 MAVEN_HOME을 잡아줬던것처럼 안드로이드SDK 설치에서도 ANDROID_HOME을 환경변수로 지정해 주어야 합니다.  위의 내용처럼 ADT bundle을 다운로드 받으셨다면 SDK의 위치는 ${ADT Bundle설치 디렉토리}/sdk 입니다. 이 위치를 ANDROID_HOME으로 지정하면 됩니다.  

세번째. Maven-eclipse플러그인인 m2e 플러그인을 설치합니다.

설치방법은 다른 이클립스 플러그인을 설치하는 방법과 동일합니다. eclipse 메뉴의 Help -> Install New Software에서 http://download.eclipse.org/technology/m2e/releases 를 입력한 뒤 플러그인을 설치합니다.  

 다음으로 Android Connector for M2E 이클립스 플러그인을 위와같은 방식으로 설치합니다. 설치 위치는 http://rgladwell.github.com/m2e-android/updates/ 입니다.  

네번째. 안드로이드 프로젝트를 생성합니다.

Maven의 android archetype을 이용해서 안드로이드 프로젝트를 생성할 수 있으나 저는 반대로 안드로이드 프로젝트 생성후 Maven프로젝트로 변환하도록 하겠습니다.  
위와 같이 기본 안드로이드 프로젝트를 생성하듯이 생성합니다. 그리고 생성된 프로젝트의 마우스 오른쪽을 눌러 Maven project로 변환합니다.

   

위의 화면에서 GroupId와 Artifact Id를 지정합니다. 여기서 봐야 할부분은 Packaging부분인데요. 안드로이드 프로젝트가 패키징 되면 .apk파일이 생성이 되는데 위의 그림에서는 Packaging에서는 apk를 선택할 수 없습니다. 하지만 이부분은 pom.xml부분에서 수동으로 설정가능하니 그냥 기본설정인 .jar로 선택하시고 finish를 누르면 됩니다.

다섯째. pom.xml에 android-maven-plugin을 추가 및 기타 설정을 합니다.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>net.krespo.android</groupId>
	<artifactId>KrespoAndroid</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>apk</packaging>
	<dependencies>
		<dependency>
			<groupId>com.google.android</groupId>
			<artifactId>android</artifactId>
			<version>1.5_r4</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>

	<build>
		<sourceDirectory>src</sourceDirectory>
		<plugins>
			<plugin>
				<groupId>com.jayway.maven.plugins.android.generation2</groupId>
				<artifactId>android-maven-plugin</artifactId>
				<version>3.6.0</version>
				<configuration>
					<androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile>
					<assetsDirectory>${project.basedir}/assets</assetsDirectory>
					<resourceDirectory>${project.basedir}/res</resourceDirectory>
					<nativeLibrariesDirectory>${project.basedir}/src/main/native</nativeLibrariesDirectory>
					<sdk>
						<path>${env.ANDROID_HOME}</path>
						<platform>16</platform>
					</sdk>
					<undeployBeforeDeploy>true</undeployBeforeDeploy>
				</configuration>
				<extensions>true</extensions>
			</plugin>

			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.0</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
이렇게 되면 기본적인 Maven-Android프로젝트는 세팅이 끝납니다. 그런데 프로젝트를 살펴보면 Android Dependencies 부분에 android-support-v4.jar가 추가 된 것을 볼수 있는데 프로젝트의 libs디렉토리에 해당 jar파일이 추가 되어 빌드패스에 추가된 것을 볼수 있습니다. 앞으로 모든 프로젝트의 라이브러리는 Maven에서 관리될 것이기 때문에 libs디렉토리의 android-support-v4.jar를 제거하고 pom.xml에 dependency를 추가합니다. 

<dependency>
	<groupId>com.google.android</groupId>
	<artifactId>support-v4</artifactId>
	<version>r7</version>
</dependency>
추가 : 댓글에 지적해주신 부분과 같이 메이픈 공식 repository에 있는 support-v4 라이브러리 버전이 너무 낮아 다른 라이브러리들과 호환문제가 발생할 수 있습니다. 그럴때는 프로젝트 libs디렉토리의 support-v4라이브러리를 삭제 하지 말고 다음과 같이 pom.xml에 선언해 주면 로컬의 라이브러리를 가져와 사용할 수 있습니다.  
<dependency>
	<groupId>com.google.android</groupId>
	<artifactId>support-v4</artifactId>
	<version>r21</version>
	<scope>system</scope>
	<systemPath>${basedir}/libs/android-support-v4.jar</systemPath>
</dependency>
위와같이 프로젝트 세팅을 완료하였습니다. 프로젝트를 빌드하는 방식은 기존의 Maven프로젝트를 빌드하듯이 package 골을 이용하여 빌드합니다. 만약 연결된 스마트 폰으로 빌드된 apk를 올려서 테스트를 하려고 한다면 다음과 같은 골을 실행시키면 됩니다.
mvn package android:deploy android:run
package - apk 파일로 생성 android:deploy - 연결된 스마트 폰으로 apk파일 배포 android:run - 스마트폰에 deploy되면 자동으로 배포된 apk를 실행   이상으로 android프로젝트에서 Maven을 사용하는 방법을 포스팅 했습니다. 개인적으로 아직 안드로이드와 Maven조합은 안정성이 있어 보이지는 않습니다. 부득이한 경우(전사 표준이라던가 하는)가 아니라면 아직 안드로이드 프로젝트에 메이븐을 적용하는 것은 시기상조인것 같네요.^^ Troubleshooting 환경변수에 ANDROID_HOME을 설정했음에도 빌드시 아래와 같은 에러가 발생한다면

org.apache.maven.plugin.MojoExecutionException: No Android SDK path could be found. You may configure it in the plugin configuration section in the pom file using <sdk><path>...</path></sdk> or <properties><android.sdk.path>...</android.sdk.path></properties> or on command-line using -Dandroid.sdk.path=... or by setting environment variable ANDROID_HOME 

 pom.xml에 직접 ANDROID_HOME을 지정해 주면 됩니다.

<properties>
  	<android.sdk.path>/your/sdk/path</android.sdk.path>
</properties>


[Oracle] start with connect by prior 사용하여 상하 관계 데이터 처리하기

Published on: 2013. 11. 14. 16:18 by louis.dev
오라클에서 데이터를 저장하다 보면 한 테이블 내에 부모 자식 관계(상하위 관계)로 표현하는 데이터가 발생될 때가 있다. 예를 들어
게시판 ↳ 공지사항 게시판 ↳ 사용자 게시판
와 같이 메뉴를 저장하는 테이블이 있다면 상위 게시판이라는 메뉴는 하위에 공지사항 게시판 메뉴, 사용자 게시판 메뉴를 하위로 가진다면, 데이터 구조는 다음과 같이 생성될 것이다.
MENUID NAME URL PARENTMENUID
1 공지사항 게시판 /notice.html 2
2 게시판 /index.html null
3 사용자 게시판 /user.html 2
만약 쿼리를 상위 메뉴 데이터를 먼저 나오게 하고 그 뒤에 하위 메뉴들을 나오게 하려면 어떻게 해야할까? 이때 Oracle에서는 start with, connect by prior를 사용하여 데이터를 셀렉트 할수 있다.
SELECT
	menuid, name, url, parentmenuid
FROM menu
START WITH parentmenuid is null	/*상위(부모)의 조건을 명시*/
CONNECT BY PRIOR menuid = parentmenuid	/*상위의 키와 하위의 키를 열결시킴*/
ORDER SIBLINGS BY menuid ASC;	/*하위데이터 정렬 조건*/
이렇게 쿼리를 사용하게 되면 다음과 같이 셀렉팅이 된다.
MENUID NAME URL PARENTMENUID
2 게시판 /index.html null
1 공지사항 게시판 /notice.html 2
3 사용자 게시판 /user.html 2

[jQuery] 엘리먼트의 속성값을 array로 가져오는 방법

Published on: 2013. 11. 14. 14:17 by louis.dev
<ul>
	<li itemid='a'>아이템1</li>
	<li itemid='b'>아이템2</li>
<ul>
jQuery에서 Selector를 통해 dom element를 가져오게되면 하나의 element를 가져오던, 여러개의 element를 가져오던간에 항상 array형태로 돌려주게 된다. 예를 들어 $("li") 를 셀렉트 하면 jQuery는 Array 형태로 선택된 엘리먼트를 리턴해 주게 된다. 만약 이때 li의 속성으로 들어가 있는 itemid의 리스트를 가져오려면 어떻게 해야 할까?
$("li").attr("itemid")
로 속성값을 array로 받을 수 있을것 같지만 첫번째 검색된 엘리먼트의 itemid 속성을 리턴해 준다. 그러면 다른 방법으로
var tempArray = new Array();
$("li").each(function(){
	tempArray.push($(this).attr("id"));
});
정도로 코딩할수 있겠다. 위에서 사용한 each는 loop문으로서 검색된 li를 한번씩 돌면서 하나하나씩 데이터를 가져오는 방식으로 그닥 효율성 있게 보이지 않는다. 그래서 jQuery에서 지원하는 method인 $.map$.makeArray를 통해 선택된 속성의 값을 array형태로 가져와 보겠다. (상세한 method설명은 위의 링크에서 확인하자) 간단히 말해 $.map은 array나 object를 새로운 array로 만들어 주는것이고,  $.makeArray는 배열처럼보이는 object를 실제 JavaScript Array형태로 만들어 주는 method이다. 위의 두개의 method를 가지고 li 속성값을 array형태로 가져오려면 다음과 같이 하면 된다.
var itemids = $.makeArray($("li").map(function(){
	return $(this).attr("itemid");
}));
위 내용처럼 map으로 선택된 엘리먼트의 속성을 가져와 array형태로 만들고 이 array를 javascript native array로 만들기 위해 makeArray를 사용하여 변환하였다.

[Maven] properties내용을 command창에서 바로 입력하기

Published on: 2013. 11. 14. 14:14 by louis.dev
Maven에서는 .properties파일 또는 pom.xml에 직접 <properties>를 통하여 DB의 접속정보라던지, 특정 dependency의 버전이라던지 하는 설정정보를 저장하여 관리할수 있다.(properties에 관한 자세한 내용은 여기에서) 이렇게 저장된 데이터들 중 pom.xml이나 properties파일에 직접 저장하기 껄끄러운데이터들이 있을 수 있다. 예를 들어 telnet이나 ftp에 로그인하기 위한 아이디와 패스워드 정보들은 pom.xml이나 .properties에 텍스트형태로 저장하게 되면 다른사람에게 그대로 노출이되어 보안에 취약하게 된다. 이런 껄끄러운 데이터들은 파일에 직접 저장하는 것이 아니라 Maven의 goal을 실행할때 파라미터로 전달하는 방법을 사용하면 된다. 아래의 설정은 Maven의 ant plugin으로 FTP를 사용하여 파일을 업로드하는 설정이다. 구체적으로 설명하지 않았지만 중요하게 봐야할 점은 FTP업로드시 userid와 password를 properties를 사용하게끔 설정했다는 것이다.
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <executions>
    <execution>
      <id>ftp</id>
      <phase>install</phase>
      <configuration>
        <tasks>
          <echo>SendFTP</echo>
          <ftp action="send" server="SERVERIP"
              remotedir="/a/b" userid="${ftp.userid}"
              password="${ftp.password}" depends="no"
              verbose="yes" binary="yes">
              <fileset dir="modules/my-module/target">
                <include name="my-static-file.zip" />
              </fileset>
            </ftp>
        </tasks>
      </configuration>
      <goals>
        <goal>run</goal>
      </goals>
    </execution>
  </executions>
  <dependencies>
    <dependency>
      <groupId>ant</groupId>
      <artifactId>ant-commons-net</artifactId>
      <version>1.6.5</version>
    </dependency>
    <dependency>
      <groupId>commons-net</groupId>
      <artifactId>commons-net</artifactId>
      <version>1.4.1</version>
    </dependency>
  </dependencies>
</plugin>
그리고 package goal을 실행할때 다음과 같이 입력한다.
$mvn package -Dftp.userid=krespo -Dftp.password=myftppassword
위에서 보듯이 ${ftp.userid}에는 krespo가 ${ftp.password}에는 myftppassword가 들어가는것을 확인해 보지 않고도 알수가 있다. 이렇듯 파라미터로 정보를 넘기려면
-D{key}={value}
형태로만 넣으면 어떠한 값이라도 동적으로 전달할 수 있게 된다.