최근에 Android SDK 버전을 r17로 업그레이드하고 나니 바뀐 점이 꽤 많더군요. 


1. 안드로이드 라이브러리 프로젝트

- bin 디렉토리에 R.class를 제외한 컴파일된 클래스를 포함하는 .jar 파일이 만들어짐.
  프로젝트이름이 my-library이면 my-library.jar 파일이 생성됨.


2. 안드로이드 앱 프로젝트

- libs 폴더의 모든 jar 파일이 'Android Dependencies' 라이브러리 변수에 자동으로 포함되어 빌드패스에 추가됨

- 라이브러리 프로젝트를 참조 라이브러리로 추가할 경우 라이브러리 프로젝트의 빌드 결과물 jar 파일이
  역시 'Android Dependencies' 라이브러리 변수에 자동으로 포함됨. 또한 라이브러리 프로젝트의 소스가 소스패스에 자동으로 추가됨.



* ADT를 통한 빌드시 자꾸 Dalvik 포맷 에러 발생하는 이슈 해결방법

- Conversion to Dalvik format failed with error 에러가 발생함

=> 앱 프로젝트에 자동으로 추가된 라이브러리 프로젝트의 소스폴더를 소스패스에서 제거해줌


* jar 파일과 소스 연결 이슈 해결방법

- 'Android Dependencies'에 포함된 jar 파일에 대해서 소스를 따로 attach할 수가 없음

=> jar 파일안에 .java 소스를 포함시키면 됨



3. ProGuard 설정

- 프로가드를 사용하려면 project.properties에서 아래 라인을 주석해제함.


proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt


- 설정파일이 proguard.cfg에서 proguard-project.txt로 변경되었으며, proguard-project.txt에는 프로젝트 specific한 내용만 작성.


4. Ant 빌드
- 여러가지 바뀜. 자세한 내용은 Android 사이트 참고.. -.-;;

* 참고하세요.

Posted by 에코지오
,

안드로이드에서 AspectJ를 사용하기 위해 이클립스 및 Ant빌드 환경을 구성하는 방법을 설명합니다.


1. AspectJ 설치

AspectJ 홈페이지(http://www.eclipse.org/aspectj/)에서 AspectJ 컴파일러를 다운로드 받아 설치합니다.

저는 개발버전인 AspectJ 1.7을 받아서 D:/Compiler/aspectj1.7 경로에 설치했습니다.

설치는 다운받은 jar 파일을 실행하면 됩니다. 


> java -jar aspectj-1.7.0.M1.jar


2. 이클립스 AJDT 플러그인 설치

이클립스 AspectJ 개발 플러그인인 AJDT를 설치합니다. http://www.eclipse.org/ajdt/downloads/ 

(이클립스 메뉴에서 Help > Install New Software... 를 선택한 후 설치 주소에 업데이트 주소 입력)

저는 개발버전인 AJDT 2.2.x를 설치했습니다. http://download.eclipse.org/tools/ajdt/37/dev/update


3. 클래스패스에 aspectrt.jar 파일 추가

aspectrt-1.7.jar 파일을 안드로이드 프로젝트의 libs 폴더에 넣어줍니다. ADT(저의 경우는 r17을 쓰고 있습니다)가 libs 폴더의 모든 jar 파일들을 자동으로 'Android Dependencies' 라이브러리에 추가해줍니다.


4. 프로젝트에 AspectJ 특성 추가

프로젝트 오른 클릭 >  Configures > Convert to AspectJ Project 를 선택하여 AspectJ 특성을 추가합니다. 그러면 프로젝트 빌더에 AspectJ Builder가 추가되고 Java Builder는 제거되며, 빌드패스에 'AspectJ Runtime Library'가 자동으로 추가됩니다.

그러나 Java Builder가 제거되면 이클립스 Problems 뷰 및 Tasks 뷰에 기존에 보였던 컴파일 에러라든가 TODO 목록이 안보이게 되므로 .project 파일에   아래와 같이 다시 Java Builder를 강제로 추가해줍니다.


  <buildSpec>

    <buildCommand>

      <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>

      <arguments>

      </arguments>

    </buildCommand>

    <buildCommand>

      <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>

      <arguments>

      </arguments>

    </buildCommand>

    <buildCommand>

      <name>org.eclipse.wst.common.project.facet.core.builder</name>

      <arguments>

      </arguments>

    </buildCommand>

    <buildCommand>

      <name>org.eclipse.jdt.core.javabuilder</name>

      <arguments>

      </arguments>

    </buildCommand>

    <buildCommand>

      <name>org.eclipse.ajdt.core.ajbuilder</name>

      <arguments>

      </arguments>

    </buildCommand>

    <buildCommand>

      <name>com.android.ide.eclipse.adt.ApkBuilder</name>

      <arguments>

      </arguments>

    </buildCommand>

  </buildSpec>


그리고  'AspectJ Runtime Library' 라이브러리 변수는 제거해줍니다.


5. aspect 작성

예를들어 src/my/app/aop/MyFirstAspect.aj 파일을 만들고 포인트컷과 어드바이스 등을 코딩해줍니다.


AspectJ 코딩 방법은 다음사이트를 참고합니다.


http://dev.anyframejava.org/anyframe/doc/core/3.2.1/corefw/guide/aop-based-aspectj.html

http://blog.daum.net/oraclejava/15858189



개발시점에서 aspect 소스 컴파일은 AJDT로 충분하지만 릴리스용 빌드생성 또는 자동빌드를 위해서는 Ant 빌드(build.xml)을 이용하는 것이 편리합니다. (이하 Android SDK r17 버전 기준 설명입니다)


AspectJ 사용을 위한 Ant 빌드 설정

(1) local.properties 파일에 아래내용을 추가합니다.


# AspectJ 컴파일러 홈

aspectj.home=D:\\Compiler\\aspectj1.7


(2) project.properties 파일에 아래내용을 추가합니다.


# AspectJ 소스 리스트 파일 경로

aspectj.src.list=aspect-list.txt


(3) custom_rules.xml 파일을 아래의 내용으로 새로 작성합니다.(기존에 파일이 존재한다면 내용을 추가)


<?xml version="1.0" encoding="UTF-8"?>

<project name="custom_rules" default="-post-compile">


  <!-- AspectJ 컴파일 추가 -->

  <taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">

   <classpath>

     <pathelement location="${aspectj.home}/lib/aspectjtools.jar" />

   </classpath>

  </taskdef>

  <!-- iajc 타스크 설명 : http://www.eclipse.org/aspectj/doc/released/devguide/antTasks.html -->

  <!-- sourceRoots, inpath, aspectpath에 대한 설명 : http://www.jroller.com/tmjee/entry/iajc_usage -->

  <target name="-post-compile">

    <echo message="Weaving aspects to .class files before dex converts .class files to .dex file" />

   <!-- aspectpathref : 라이브러리에 속한 애스펙트도 적용할 경우 설정 -->

    <iajc destDir="${out.classes.absolute.dir}"

          bootclasspathref="android.target.classpath"

          classpathref="project.libraries.jars"

          classpath="${aspectj.home}/lib/aspectjrt.jar"

          sourceroots="${source.absolute.dir}"

          inpath="${out.classes.absolute.dir}"

          aspectpathref="project.libraries.jars"

          Xlintwarnings="true"

          showWeaveInfo="true"

          encoding="${java.encoding}"

          source="${java.source}"

          target="${java.target}">

    </iajc>

  </target>


</project>


만약 프로젝트 유형이 안드로이드 '라이브러리' 프로젝트라면 아래와 같이 -post-compile 타겟을 정의합니다.


    <echo message="Weaving aspects to .class..." />

    <iajc destDir="${out.classes.absolute.dir}"

          bootclasspathref="android.target.classpath"

          classpathref="project.libraries.jars"

          classpath="${aspectj.home}/lib/aspectjrt.jar"

          Xlintwarnings="true"

          showWeaveInfo="true"

          encoding="${java.encoding}"

          source="${java.source}"

          target="${java.target}">


      <sourceroots>

        <pathelement location="${source.absolute.dir}" />

        <pathelement location="${gen.absolute.dir}" />

      </sourceroots>


      <!--

       inpath="${out.classes.absolute.dir}"

       => 이 옵션을 적용하면 앱에서 라이브러리의 애스펙트도 적용하도록 

            설정한 경우 bad WeaverState.Kind: -115 에러 발생함

      -->

    </iajc>


    <!-- 라이브러리 프로젝트인 경우 -compile 타겟에서 생성된 classes.jar를 위빙된 클래스로 교체 -->

    <if condition="${project.is.library}">

      <then>

        <echo>Overwrite library output jar file with weaved classes...</echo>

        <jar destfile="${out.library.jar.file}" update="false">

          <fileset dir="${out.classes.absolute.dir}"

                   includes="**/*.class"

                   excludes="${manifest.package.path}/R.class ${manifest.package.path}/R$*.class ${manifest.package.path}/Manifest.class ${manifest.package.path}/Manifest$*.class ${manifest.package.path}/BuildConfig.class" />

          <fileset dir="${source.absolute.dir}"

                   excludes="**/*.java ${android.package.excludes}" />

        </jar>

      </then>

    </if>




(4) proguard-project.txt에 다음 내용을 추가합니다.


# aspect 클래스 및 aspect가 적용되는 클래스에서 AspectJ 라이브러리를 참조할 수 없다는 경고 제거

# (can't find referenced class)

-dontwarn org.aspectj.**


# 패키지 변경 금지(주석해제시 런타임에 java.lang.NoSuchMethodError 에러 발생)

#-repackageclasses ''

#-allowaccessmodification


# AspectJ 클래스 보존

-keep class org.aspectj.**


# Aspect 클래스 및 멤버 보존

-keep @org.aspectj.lang.annotation.Aspect class * { *; }

-keepclasseswithmembers class * {

    public static *** aspectOf();

}


# around 어드바이스가 적용되는 target 클래스에서 around 어드바이스 메소드를

# 참조할 수 없다는 경고 제거(can't find referenced method) : aspect 클래스를 지정

-dontwarn my.app.aop.**

(또는 -dontwarn my.app.**.*Aspect 식으로 설정)


(5) aspect 소스 리스트 파일 작성

aspectj.src.list 속성으로 정의한 aspect-list.txt 파일을 생성하고, aspect 소스 리스트를 한줄에 하나씩 나열합니다.

경로는 프로젝트 루트에 대한 상대경로입니다.


src/my/app/aop/MyFirstAspect.aj

src/my/app/aop/MySecondAspect.aj

...


Posted by 에코지오
,
현재 내 로컬PC에는 여러 개의 이클립스가 설치되어 있다. 아마도 대부분의 SI개발자들은 보통 2개 이상의 이클립스가 한 PC에 존재하게 되는데, 이렇게 되면

  • 디스크를 많이 잡아먹는다
  • 설정을 공유하기가 쉽지 않다
  • 수많은 플러그인의 설치 및 관리가 쉽지않다
이 중에서 중복된 플러그인 파일로 인한 디스크 낭비와 추가로 플러그인을 설치하기 위한 에포트 낭비 문제를 해결할 아이디어가 생각났다. 바로 Maven의 레포지토리 개념을 이클립스 플러그인 관리에도 도입하는 것이다.

메이븐 레포지토리처럼 이클립스 플러그인들을 중앙 레포지토리에 몰아넣고, 플러그인 설치시에는 중앙레포지토리로부터 자동으로 로컬 레포지토리에 다운로드한다. 그리고 실제 이클립스를 띄우면 이클립스는 로컬 레포지토리의 플러그인을 로딩한다.

이클립스 플러그인 관리 화면에서는 사용자가 로컬 또는 리모트 레포지토리에 존재하는 플러그인들을 검색,설치,제거,업그레이드 등의 작업을 할 수 있게 지원한다. 플러그인들 사이의 의존성도 자동으로 체크된다.

뭐 플러그인이 너무 많아서 관리가 쉽진 않겠지만 매번 플러그인 홈페이지 주소 찾고 지원하는 이클립스 버전확인하고 업데이트 URL복사하여 이클립스 화면에 붙여넣고 등등 이제는 너무 귀찮다.






Posted by 에코지오
,