Thursday, September 17, 2015

[AndroidAnnotations_Build] 4. Maven build.

Maven Build 환경에 대한 구조를 파악하기 전에 Maven 자체가 무엇이며 Maven으로 할 수 있는 것이 무엇인지 알아보았습니다.

1. Maven 이란?

Maven은 Java를 위한 Build Tool이자 프로젝트 전반의 LifeCycle 관리를 목적으로 하는 툴입니다. Maven을 설치하면 Console 명령어를 이용하여 사용할 수 있습니다. 하지만 Eclipse를 이용하면 Console 명령어가 아닌 m2e plugin을 활용하여 빌드를 사용할 수 있습니다. Maven에서 핵심 키워드는 pom.xml, phase , goal이며 아래에서 이에 대한 설명을 진행하도록 하겠습니다.

2. pom.xml?

POM은 Project Object Model의 약자로 Maven을 이용하는 Project의 root에 존재합니다. 해당 프로젝트에 대한 Dependency, Information 같은 것들을 작성하며 사용합니다. pom.xml에 대한 설명은 다음의 링크 (POM Reference) 에서 확인할 수 있습니다. 그럼 여기서 가장 많이 사용되는 label들에 대한 파악을 해보도록 하겠습니다.

2.1. Maven Coordinates (GroupId,ArtifactId,Version,Packaging)



  4.0.0
 
  com.home
  my-project
  1.0
  war



'groupId:artifactId:version'는 모두 pom.xml 파일에 있어야 하는 조건입니다. 'groupId, vesrion'의 경우 부모로 부터 선언된경우라면 필요하지 않습니다. 'groupId'는 조직이나 프로젝트의 일반적인 고유 값이며, 'artifactId'는 일반적으로 프로젝트로 알려져있는 이름입니다. 'version'은 이름을 짓는것에 마지막 규칙으로 artifact 저장소의 코드 버전을 나누는 것입니다.

'packaging'은 프로젝트의 artifact type입니다. 기본으로 지정되있는 것은 jar이며, 새로운것을 지정하기 위해서는 'pom, jar, maven-plugin, ejb, war, ear, rar, par'이 있습니다. 이 정의는 build lifecycle 지정에 사용됩니다.

3. phase

말 그대로 단계를 뜻하며, Maven 환경에서의 LifeCycle 단계를 의미한다. LifeCycle은 3가지로 분류할 수 있다.

3.1. Default LifeCycle Maven Phase

  1. validate 프로젝트가 정상적인지, 필요한 모든 정보가 있는지 검증하는 단계.
  2. compile 프로젝트의 소스코드를 컴파일 하는 단계.
  3. test unit test framework를 이용하여 테스트 소스코드 컴파일 하는 단계.
  4. package 컴파일된 소스를 배포하는 형태로 만드는 단계.
  5. integration-test통합 테스트를 할 수 있는 환경에 패키지를 배포하는 단계.
  6. verify package를 실행하고 검증해보는 단계
  7. install 패키지를 로컬 저장소에 설치하는 단계
  8. deploy 만들어진 패키지를 외부 저장소에 release 하는 단계

3.2. Other LifeCycle

  1. clean Build전에 생성된 artifact를 청소하는 단계
  2. site 해당 프로젝트의 Document를 생성하는 단계

4. Maven Install

기본적으로 Eclipse나 Intellij 를 사용한다면 해당 IDE 에서 빌드 작업을 수행하기 때문에 따로 maven을 설치하지 않아도 실행되었다. 하지만mvn install 와 같은 CommandLine 명령어를 수행시키기 위해서는 maven을 install을 컴퓨터에 해두어야 한다. 먼저 Install을 하기 위해서는 Download Link 링크로 이동하여 다운로드 받으면 된다.

윈도우 환경에서 진행하였기 때문에 zip 파일을 다운로드 받았다. Download 받은 뒤 Window 환경이었기 때문에 환경변수 아래와 같이 지정해 주었다.

- MAVEN_PATH
- C:\Development\maven\apache-maven-3.3.3\bin

- Path
- ...;%MAVEN_APTH%; ...

위의 작업을 실행하면 Command Line에서의 mvn -v를 치면 아래와 같은 화면이 출력된다.

참고 논문 및 사이트

1. Maven Documentation - https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html

2. 메이븐(Maven) 5분 개념 설명 http://qwertyju.egloos.com/5716209

3. Maven 기초 사용법 http://javacan.tistory.com/129

Sunday, September 13, 2015

[AndroidAnnotations_Build] 3. AndroidAnnotations Build Option

Gradle build script에서 android-apt script 내용 변경이 가능합니다. CustomizeAnnotationProcessing 페이지에서 공식 wiki 를 확인 가능합니다. 간략하게 특정 기능에 대한 어떤 Option이 있는지 확인해보도록 하겠습니다.

1. androidManifestFile

Default - 부모 폴더에서 부터 재귀적으로 AndroidManifest.xml을 찾습니다. 이 부분에 있어서 확인이 필요하다고 생각한 부분은 부모 폴더가 어디인지를 파악하지 못하였습니다.(이걸 찾아야할텐데..) 따라서 아래와 같이 작성해주어야만 찾습니다.

apt {
    arguments {
        androidManifestFile variant.outputs[0].processResources.manifestFile
    }
}

위과 같이 작성해야만 되는데 위의 script내용물 또한 자세한 파악을 못하였습니다. 이 부분에 대해서는 파악을 하는데로 포스팅 업데이트를 하도록하겠습니다.

2. resourePackageName

Default의 경우 AndroidManifest.xml의 Application Package로 부터 추출되어집니다. 따라서 아래 코드의 package 부분이 추출되어집니다.

 

따로 R class에 대한 변경이 필요하지 않을 경우에는 작성하지 않아도 됩니다. 작성이 필요하다면 아래 script와 같이 작성해주면됩니다.

apt{
    arguments {
        resourcePackageName "your.package.name"
    }
}

3. logFile, logLevel, logAppenderConsole, logAppenderFile

이 옵션의 경우 AndroidAnnotations에서 사용하는 커스텀 로그로 파일 생성시에 작성되는 로그입니다. 해당 되는 로그파일은 {outputFolder}/andrioannotations.log에 작성되어진다.

logLevel은 trace, debug, info, warn, error 이고 default 값은 deubg이다. Log가 출력되는 곳의 기본은 "FileAppender(File)", "MessageAppeder(IDE)" 이다. logAppenderConsole의 경우는 true,false값이며 console에 log가 찍히도록 해준다. logAppenderFile의 경우에는 default는 true이며, false로 할경우 File에 작성되는 log를 제외해준다. 작성방법은 다음과 같다

apt{
    arguments {
        logLevel 'INFO'
        logFile '/var/log/aa.log'
        logAppenderConsole false
        logAppenderFile false
    }
}

Saturday, September 12, 2015

[AndroidAnnotations_Build] 2. Setting AndroidAnnotations Build (Use Gradle)

1번 포스팅에 이어서 AndroidAnntations를 빌드하는 방법에 대한 포스팅을 하도록 하겠습니다. 동일하게 AndroidStudio를 사용하고 Gradle을 이용하였습니다. 빌드를 하기 위해서는 몇가지 세팅 방법이 필요합니다. 이 부분은 AndroidAnnotations Wiki Page를 참고하였습니다. 해당 페이지의 Gradle 페이지를 참고하였습니다.

1. Annotations Processor 사용을 위한 Annotation processor 활성화 시키기

먼저 AndroidAnnotations를 사용하기 위해서는 Android Studio의 Compile 시점의 Annotation Processor를 활성화 시켜야 합니다. " File → Other Settings → Default Settings... "으로 들어갑니다.

다음 과정으로는 " Build, Execution, Deployment → Compiler → Annotation Processor "으로 들어갑니다. 들어가게되면 아래의 사진과 같이 Anntation Processor가 활성화 되지 않은것을 확인할 수 있습니다.

여기서 " Enable annotation proceesing " Check Box를 아래 사진과 같이 활성화 시켜주면 됩니다.

해당 작업을 "OK" 버튼을 눌러 활성화 시켜주면 Annotation Processor가 활성화 되게 됩니다.

2. Gradle 빌드에 android-apt 설정 추가하기

2.1 android-apt란?

Android-apt Bitbucket 홈페이지 Readme를 통하여 확인할 수 있습니다. Android-apt 는 gradle plugin으로 Android studio 에서 annotation processor를 사용할 수 있도록 도와주는것입니다. 이것은 마지막 apk 추출이나 library에는 적용이 안되며 오직 compile 시에만 작동할 수있도록 도와주는것이며, annotations process를 통해 생성되는 코드에 대한 소스 경로를 결정해줍니다.

2.2 Gradle 빌드에 android-apt 추가

먼저 상위 build.gradle 파일에 아래와 같이 dependency를 추가해줍니다. ('// *' 이 추가된 라인입니다.)

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'
        classpath "com.neenbedankt.gradle.plugins:android-apt:1.7" // ** 
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

다음은 Application의 depenecy의 gradle을 아래와 같이 depenecy와 정의를 추가해 줍니다.('// *' 이 추가된 라인입니다.)

def AAVersion = "3.3.2" // *

apply plugin: "com.android.application"
apply plugin: "com.neenbedankt.android-apt" // *

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.0"

    defaultConfig {
        applicationId "com.juranoaa.myapplication"
        minSdkVersion 23
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }
}

apt { // *
    arguments { // *
        androidManifestFile variant.outputs[0].processResources.manifestFile // *
    } // *
} // *

dependencies {
    compile fileTree(dir: "libs", include: ["*.jar"])
    apt "org.androidannotations:androidannotations:$AAVersion" // *
    compile "org.androidannotations:androidannotations-api:$AAVersion" // *
}

그리고 AndroidAnnotations를 사용한 Activity를 추가해줍니다.

package com.juranoaa.myapplication;

import android.app.Activity;

import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Fullscreen;

@Fullscreen
@EActivity(R.layout.activity_main)
public class AAMainActivity extends Activity{
}

"Build → Rebuild Project"을 선택하게 되면 AndroidAnnotations Build 가 수행되게 됩니다.

완료가 되면 다음과 같이 generated 폴더 하위에 다음과 같은 클래스 파일이 생성되게 됩니다.

다음 포스팅에서는 AndroidAnnotations build시 사용되는 내용에 대해서 포스팅하도록 하겠습니다.

참고 논문 및 사이트

1. AndroidAnnotations Wiki Configuration https://github.com/excilys/androidannotations/wiki/Configuration

[AndroidAnnotations_Build] 1.Gradle, Android Studio Gradle File

먼저 AndroidAnnotations 프로젝트에 대한 설정 방법을 설명하기에 앞서 Android Build에 사용되는 Gradle과 Gradle의 장점 프로젝트 구성을 설명하도록 하겠습니다.

1. Gradle

1.1. Gradle 이란?

Gradle 이란 Groovy DSL(Domain Specific Language)로 작성하여 빌드 자동화를 시키는 툴이다. Gradle은 필요한 프로젝트에 빌드 스크립트를 추가하여 주입하는 방식이다. 또한 Gradle은 Java 진영에서 많이 사용해왔던 Maven, Ant 툴의 단점은 버리고, 장점을 취한 빌드 툴이다.

1.2. Gradle 장점

  1. Groovy 기반인 DSL을 사용한다.
  2. Multi Project Build Configuration Injection 방식을 사용한다.
  3. Dependecncies 관리의 다양한 방법을 제공한다
  4. Build의 구조화가 가능하다.
  5. 빌드 내용을 XML이 아닌 Groovy Script로 작성된다.

1.3. Maven과의 차이점

Maven은 Multi Project 구성시 상속구조로 사용한다. 반면에 Gradle의 경우 Configuration injection(주입 방식)을 사용한다. 또한 XML을 사용할 경우 쓸데 없이 길어지며 중복성이 발생하여 가독성이 떨어진다. 반면에 Gradle의 경우 Groovy Script를 이용하여 이를 해결하고 있다.

2. Android Gradle

기본 Android Studio에서 MainActivity가 존재하는 프로젝트를 생성하면 아래의 이미지와 같은 구조로 생성되어 있습니다.

가장 외부에 있는 "build.gradle" script 내용은 아래와 같습니다.

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.3.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

위 build script dependencies 부분에는 우리가 사용하는 외부 dependency는 입력하면 정상적으로 수행되지 않는다. 해당되는 dependecy는 프로젝트 application의 build script에 추가해야한다. 또한 현재 com.android.tools.build 버전의 경우 1.3.1이 (1.3.1 Link) 추가되어있다. 따라서 현재는 1.3.1을 적용하여도 된다.

Project의 repository의 경우 자동생성되는 저장소는 jcenter() 이었다. 하지만 이부분에 있어 기존에는 mavencentral()이었기 때문에 차이점을 확인해보았다. 차이점은 아래와 같다.

  • jcenter는 Android의 gradle plugin이 사용하는 새로운 기본 저장소입니다.
  • jcenter는 Bintray에 있는 Java repostiory입니다. 이 저장소는 Java, Android oss libararies, packages, component가 있는 가장큰 저장소입니다.
  • MavenCertral의 경우 http 요청만 지원할 뿐 https는 지원하지 않는다. 반면에 jcenter는 Https로 보장된 CDN(Content Delivery Network)서버로 사용되고 있다.
  • jcenter는 많은 추가 repository와 artifact를 포함한 mavencetnral의 상위 집합입니다.
  • Jcenter 사람이 말하길 성능면에서 maven central보다 좋다고 주장합니다.
  • Bintray는 Maven central 이 접근하는 package 접근과 다른 접근을 사용합니다.
  • 만약 Maven Cenrtal 패키지에있는 것이 필요하다면 버튼 클릭만으로 Bintray에서 사용할수 있도록 한다.

따라서 앞으로는 jcenter() 를 사용하면될것 같다.

안에 Application 모듈에 있는 "build.gradle" script는 아래와 같다. 컴파일에 사용되는 버전은 현재 나오게 된 23 마시멜로버전을 사용하였다.

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.0"

    defaultConfig {
        applicationId "com.juranoaa.myapplication"
        minSdkVersion 23
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

위의 build script에서 dependencies부분에 사용할 library import하여 사용한다. 또한 여기서 내가 의문점을 가졌던 부분은 apply plugin: 'com.android.application' 이다. 이 부분의 경우 기존에 다음과 같이 표현되었다.apply plugin: 'android'. 이 부분의 경우 Deprecated 되있었는데 해당되는 이유는 찾지 못하였다. 추정하건데 FQCN(Fully Qualifid Class Name)으로 패키지명부터 작성하여 정확한 plugin을 부르기 위함이라고 생각한다.

dependencies 에 있는 compile fileTree(dir : 'libs', include : ['*.jar']) 이 부부은 gradle을 통해 추가한 library가 아닌 직접 libs 폴더에 추가한 library에 대한 compile을 하기 위해서입니다.

buildTypes 부분의 경우에는 Android Documentation을 참조해보면 apk 추출시 쓸모없는 파일에 대해서 제외를 해주는 부분이다. 해당되는 부분은 자세한 내용은 추후 다른 포스팅에서 다루도록 하겠습니다.

그리고 Android Congifuration Gradle Build를 참고 하면 여러 내용들에 대한 자세한 내용을 확인할 수 있습니다.

참고 논문 및 사이트

1. AndroidAnnotations Wiki Get Started Page - https://github.com/excilys/androidannotations/wiki/Configuration

2. Library Project - https://github.com/excilys/androidannotations/wiki/Library-projects

3. Maven을 넘어 Gradle로 가자 - http://egloos.zum.com/kwon37xi/v/4747016

4. Gradle 설정 파일 및 기본개념 - http://www.slipp.net/wiki/pages/viewpage.action?pageId=11632748

5. Androi Studio - Migration from Maven Central to JCenter - http://blog.bintray.com/2015/02/09/android-studio-migration-from-maven-central-to-jcenter/

Saturday, August 29, 2015

[AndroidAnnotations_EnhancedComponent] - @EActivity

1. @EActivity Basic

1.1 Android

@EActivity의 사용은 안드로이드 Activity 클래스를 만들 때 사용하게 된다. 가장 기본적으로 사용되는 Annotation이라고 볼 수 있다. @EActivity annotation은 반드시 layout id가 필요하며, 해당 값은 activity 의 ContentView로 연결된다. 따라서 이것을 Framework를 사용하지 않고 안드로이드 코드로 작성한다면 아래와 같은 코드가 작성된다.

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    
}

1.2 AndroidAnnotations

반면에 이를 AA Framework를 이용하게 되면 아래와 같이 코드가 간결해짐을 알 수 있다.

import android.app.Activity;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;

@EActivity(R.layout.activity_main)
public class AAMainActivity extends Activity{
}

2. Intent Activity

2.1 Android

Android 에서 기본적으로 Activity간에 이동을 하는 경우에 intent를 사용하게 되는데, Intent의 연결도 한결 간결하게 표현됨을 알 수 있다. 먼저 Intent 객체를 생성하여 해당 클래스에 대한 intent 객체를 생헝하고 startActivity를 이용하여 해당 intent를 실행하는 구조로 작동된다. 따라서 기존 Android 소스 코드는 다음과 같이 표현된다.

Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);

2.2 AndroidAnnotations

해당 Framework를 사용하여 Activity를 @EActivity를 이용하여 클래스 파일을 생성할 경우에는 LoginActvity_.class로 클래스가 생성되고 따라서 intent를 호출하는 문법은 아래와 같이 변경되게 된다.

Intent intent = AALoginActivity_.intent(AAMainActivity.this).get();
startActivity(intent);

또한 해당 문법은 아래와 같이 표현될 수 있다.

AALoginActivity_.intent(getApplicationContext()).flags(Intent.FLAG_ACTIVITY_NEW_TASK).start();

Wednesday, August 26, 2015

[What is java annotation 03] - Creating your Own Annotations?

3. Creating your Own Annotations

3.1. Annotation 선언 방법

Custom Annotation을 만들기 위해서는 class 또는 interface로 아래와 같이 코드가 구현되어야 합니다.

public @interface Man {
    boolean isMan() default true;
    int age();
    String name();
    String[] have();
}

위와 같이 Annotation을 선언한 뒤 아래와 같이 해당 값들을 입력해야 Annotation 사용이 가능합니다. "Default" value를 지정할 경우에는 따로 값을 지정하지 않아도 사용 가능합니다.

@Man( age = 99, name = "Francis Kim", have = { "cellphone", "watch" })
public class MyAnnotationUse {
    ...
}

3.2. Annotation 용도 지정방법

아래와 같이 @Retention Annotation을 추가하면 해당 Annotation에 대한 용도 지정이 가능합니다.

@Retention(RetentionPolicy.RUNTIME)
public @interface Man {
    ...
}

3가지의 종류가 있다.

  • SOURCE : 컴파일러가 사용하고 클래스 파일 안에 포함되지 않는 경우
  • CLASS : 컴파일시 클래스 파일 안에 포함되나 VM에서 무시하는 경우
  • RUNTIME : 컴파일시 포함되고 VM에서 인식 하는 경우가 있다

3.2. Annotation 범위 지정방법

ElementType에 8가지 범위가 선언이 가능하며, 선언되지 않은 범위에 대해 Annotation을 사용할 경우 해당 Annotation은 무시됩니다. 또한 타겟은 여러개 지정이 가능합니다.

@Target({ElementType.TYPE, ElementType.FIELD})
public @interface Man{
 ...
}
  • TYPE : 클래스, 인터페이스, Annotation, 또는 열거형 타입
  • FIELD : 필드 또는 열거형 타입의 값
  • METHOD : 메소드
  • PARAMETER : 메소드의 인자
  • CONSTRUCTOR : 클래스 생성자
  • LOCAL_VARIABLE : 메소드 내부 변수
  • ANNOTATION_TYPE : Annotation 타입
  • PACKAGE : 패키지

참고 논문 및 사이트

1. Java Annotation: 인터페이스 강요로부터 자유를… - http://www.nextree.co.kr/p5864/

2. Java Annotations - http://tutorials.jenkov.com/java/annotations.html

3. Annotation과 Reflection, 그리고 코드 속의 MetaData - http://kang594.blog.me/39704853

[What is java annotation 02] - Annotation Basics?

2. Annotation Basics

Java annotation은 다음과 같이 표현됩니다.

@Deprecated, @Override, @SuppressWarings

위 3가지 Annotation의 경우에 Compiler instructions으로 이미 Java에서 제공되는 것 입니다.

2.1. @Deprecated

Class, Method, Field에 해당 annotation을 표시해두면 해당되는 것들은 사용하지 마라 라고 권고하는 것 입니다. 해당 annotation은 compile시에 warning(경고)를 표시해줍니다.

@Deprecated
public class DeprecatedClass {

    public DeprecatedClass() {
    }

    @Deprecated
    public static final String deprecatedStr = "Deprecated"

    @Deprecated
    public void deprecatedMethod(){
    }

}
public class Main {

    public static void main(String[] args) {
        // Class Call
        DeprecatedClass deprecatedClass = new DeprecatedClass();
        // Method Call
        deprecatedClass.deprecatedMethod();
        // Field Call
        String str = DeprecatedClass.deprecatedStr;
    }
}

2.2. @Override

@Override annotation는 superclass(부모 클래스)에 대해 상속 받아 override 할 경우에 사용됩니다. 만약 superclass에 해당 method가 없다면, compile시 error를 발생시킵니다.

public class ParentClass {

    public void extendMethod(){

    }

}
package com.example.annotation;

public class ChildClass extends  ParentClass{

    @Override
    public void extendMethod() {
        super.extendMethod();
    }

    @Override
    public void notExtendMethod(){

    }

}

2.3 @SuppressWarnings

@SuppressWarning 는 warning을 발생하는 것들에 대하여 warning을 제거하는 용도로 사용됩니다. Deprecated된 명령어를 사용하거나, 보장되지 않는 형변환을 할 때 등 컴파일 시점에 warning을 발생하는 경우에 대해서 warning을 제거할 수 있도록 합니다.

@SuppressWarnings("deprecation")
public class SuppressWarningsClass {

    public void method(){
        DeprecatedClass deprecatedClass = new DeprecatedClass();
    }

}

참고 논문 및 사이트

1. Java Annotation: 인터페이스 강요로부터 자유를… - http://www.nextree.co.kr/p5864/

2. Java Annotations - http://tutorials.jenkov.com/java/annotations.html