관리 메뉴

나만을 위한 블로그

[Android] 안드로이드 스튜디오에서 나만의 라이브러리 만들고 적용하기(AAR) 본문

Android

[Android] 안드로이드 스튜디오에서 나만의 라이브러리 만들고 적용하기(AAR)

참깨빵위에참깨빵_ 2021. 11. 10. 21:32
728x90
반응형

※ 이 포스팅은 안드로이드 스튜디오 4.2.2 버전을 기준으로 작성됨

 

앱을 개발하다 보면 상용구처럼 자주 쓰는 클래스, 메서드가 있다. 이걸 따로 라이브러리처럼 만들어서 쓰면 좋겠다고 생각했는데 찾아보니 그 방법이 있었다.

이것에 대해선 이미 잘 설명해주신 분이 계신다.

 

https://realapril.tistory.com/55

 

안드로이드 라이브러리(aar) 만들기

특정 프로젝트에 종속되지 않고 stand alone 빌드할수 있으며, 라이브러리 내용이 수정될 때 마다 매번 aar파일을 복붙할 필요가 없는 방식으로 aar 라이브러리를 만들것이다. 물론 https://today-shot.tist

realapril.tistory.com

 

그러나 조금 옛날 버전의 안드로이드 스튜디오로 설명되어 있고, 코틀린 기반으로 설명되어 있어서 자바로 작성하면서 적용한 과정을 포스팅하려고 한다.

서두에도 썼지만 내가 사용하는 안드로이드 스튜디오 버전은 4.2.2다.

 

 

먼저 프로젝트를 새로 만들어야 한다. 처음 생성할 때 No Activity를 선택하는 게 편하다.

 

 

이름 대충 짓고 No Activity인 상태로 프로젝트를 생성한다. 난 TestLibraryModule이란 이름으로 만들었다.

그리고 아래 과정을 거쳐야 한다. 모두 끝냈다면 우상단의 Sync now를 눌러 적용한다.

 

  • 프로젝트 수준 gradle, 앱 수준 gradle을 하나로 합친다. 난 앱 수준 gradle에 프로젝트 수준 gradle 파일에서 필요한 내용들을 넣었다.
  • apply plugin: 'com.android.application'을 apply plugin: 'com.android:library'로 바꾼다
  • 앱 수준 gradle 파일에 있는 defaultConfig 안의 applicationId를 지운다
  • sourceSets { ... } 를 추가한다. 중괄호 안에 들어갈 내용은 아래에서 확인한다
  • implementation fileTree(dir: "libs", include: ["*.jar"]) 를 앱 수준 gradle 안의 dependencies 안에 넣는다
  • dependencies 안에 repositories { ... } 를 추가한다. 프로젝트 수준 gradle의 allProjects { ... } 안에 있던 내용을 말한다

 

2번째 내용대로 하기 전에 앱 수준 gradle을 보면 안드로이드 스튜디오 4.2.2 기준으로 이렇게 되어 있다.

 

 

난 설명글에 충실해서 모든 내용을 똑같이 따라했기 때문에 저 부분도 설명글대로 수정해서 진행했다. 저 부분에서 application을 library로 고쳐도 되는지는 확인하지 않았다.

최종 형태는 아래와 같다.

 

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.2.2"

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

apply plugin: 'com.android.library'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src/main/java']
            res.srcDirs = ['res']
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    repositories {
        google()
        jcenter()
    }
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'com.google.android.material:material:1.4.0'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

 

이렇게 적용됐다면 왼쪽의 폴더 트리가 이런 모양이 되어야 한다.

 

이제 안드로이드 스튜디오는 잠시 끄지말고 내버려두고, 파일 탐색기를 열어 이 프로젝트 폴더 위치로 이동한 다음 app 폴더 안으로 들어가서 libs 폴더, src 폴더, build.gradle 폴더를 밖으로 빼낸다.

 

 

그럼 이 팝업이 나온다.

 

 

그냥 덮어쓰기를 누르면 된다. 이 버튼을 누른 이후 프로젝트 폴더의 내용물은 아래와 같아야 한다.

 

 

그리고 app > src > main으로 들어가서 res 폴더, 매니페스트 파일도 위 사진의 위치로 옮겨준다.

 

 

여기까지 왔다면 이런 형태로 폴더, 파일들이 위치해 있어야 한다.

 

 

이 상태에서 app 폴더는 지운다. 최종 화면은 아래와 같다.

 

 

이제 이 폴더는 내버려두고 다시 안드로이드 스튜디오로 돌아오면 폴더들이 빠르게 사라지는 게 보인다. 무시하고 Gradle Scripts > settings.gradle(Project Settings) 파일을 열어 수정한다. 이 파일을 열면 아래와 같은 형태다.

 

rootProject.name = "TestLibraryModule"
include ':app'

 

여기서 2번째 문장을 지운다. 그리고 Sync now를 눌러 변경사항을 적용한다.

최종화면은 아래와 같다.

 

 

그리고 왼쪽의 폴더 트리는 이 모양이어야 한다.

 

 

이제 com.example.testlibrarymodule 폴더에 클래스를 만들고 사용할 메서드들을 정의해준다. 대충 2개의 메서드를 정의했다.

 

package com.example.testlibrarymodule;

import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class TestLibrary {
    public void toast(Context context, String text) {
        Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
    }

    public void moveActivity(Context context, Class<?> cls) {
        Intent intent = new Intent(context, cls);
        context.startActivity(intent);
    }
}

 

필요한 메서드들을 정의했으면 오른쪽을 본다. 그러면 세로쓰기로 gradle이 적혀있는데 이걸 눌러 Tasks > other > assembleRelease를 찾은 다음 더블클릭해 실행한다.

 

 

10초 정도면 완료된다. 만약 이 과정에서 themes 폴더를 삭제하라거나 매니페스트 파일 안의 내용을 수정하라고 하면 그대로 따르면 된다.

결과물은 build > outputs > aar 폴더로 들어가면 확인할 수 있다. TestLibraryModule-release.aar이란 이름의 파일이 보일 것이다.

 

 

이제 나만의 라이브러리가 만들어졌다. 새 프로젝트를 만든 뒤, 좌상단의 Android를 클릭해 Project로 바꾸고 저 aar 파일을 app > libs 폴더 안에 복붙한다. 최종 결과는 아래와 같아야 한다.

 

그리고 새 프로젝트의 setting.gradle(Project Settings) 파일을 열어 수정해준다.

 

include ':app', ':module'
project(':module').projectDir=new File('C:/Users/msi/Desktop/AndroidStudioProjects/TestLibraryModule')
rootProject.name = "TestLibraryExecute"

 

수정 시 중요한 사항은 아래와 같다.

 

  • File() 내부, rootProject.name의 값은 대소문자를 구별해 적는다
  • include와 2번 줄 첫 부분(project()) 안에는 소문자로 module을 입력해야 한다
  • 이 순서를 하나라도 바꾸면 변경사항 적용이 되지 않는다. 이 순서로 해야 하는 듯하다

 

다 했다면 다시 Project를 Android로 바꿔 보기 편하게 바꾼 뒤, 새 프로젝트의 앱 수준 gradle 파일에 아래 문장을 추가한다.

 

implementation project(":module")

 

우상단의 Sync now를 눌러 변경사항을 적용해주면 왼쪽 폴더 트리에 Module이란 폴더가 생기고 그 안에 아까 만들었던 자바 파일이 보인다.

 

 

이제 드디어 내가 만든 라이브러리를 불러와 써보자. 메인 액티비티에 TestLib까지만 입력하면 자동완성되는 것도 보인다.

 

 

액티비티도 대충 하나 새로 만들어주고 위에서 작성했던 함수들을 사용해보자.

package com.example.testlibraryexecute;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import com.example.testlibrarymodule.TestLibrary;

public class MainActivity extends AppCompatActivity {

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

        TestLibrary library = new TestLibrary();
        library.toast(this, "테스트");
        library.moveActivity(this, OtherActivity.class);
    }
}

 

이제 에뮬레이터든 실제 기기로든 빌드해보자.

그러나 여기까지 와서 이런 에러가 발생할 수 있다.

 

Manifest merger failed : Attribute application@theme value=(@style/Theme.TestLibraryExecute) from AndroidManifest.xml:12:9-56 is also present at [:module] AndroidManifest.xml:15:9-55 value=(@style/Theme.TestLibraryModule). Suggestion: add 'tools:replace="android:theme"' to <application> element at AndroidManifest.xml:6:5-21:19 to override.

 

쫄지 말자. 그냥 매니페스트에 저 tools:replace 어쩌고 하는 문장을 복붙해주고 임포트하면 끝이다.

저걸 적용한 매니페스트 파일은 아래와 같은 모양이다.

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.testlibraryexecute">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        tools:replace="android:theme"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.TestLibraryExecute">
        <activity android:name=".OtherActivity"></activity>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

이제 실행해보면 토스트와 로그가 나오면서 저절로 화면이 바뀌는 걸 볼 수 있다.

 

 

이제 이것 말고도 서버 통신하는 준비 코드라던가, 다이얼로그 등을 사용하기 위한 상용구 코드들을 모듈 형태로 가져다 쓸 수 있게 됐다. 잘만 응용하면 밑바닥부터 앱을 만들게 되었을 때 개발 시간을 많이 단축시켜줄 수 있을 것 같은 방법이다.

반응형
Comments