Custom Template Plugin for Android Studio

DevOks·2021년 10월 13일
1
post-thumbnail

안드로이드 스튜디오(203.7717.56)용 File Templates 플러그인 개발환경 구축 가이드

What is File Templates Plugin?

(https://plugins.jetbrains.com/docs/intellij/templates.html)

안드로이드 스튜디오(IDE)등을 사용하여 소프트웨어를 개발 하면서, 동일한 기본 파일구조와 공통의 코드들을 반복적으로 생성 및 작성 해야만 할 때가 있습니다. 그래서 안드로이드 스튜디오에는 '파일 생성 템플릿'(File Templates : IDE-File-New-Activity,Fragment등 탬플릿선택)이라는 기본 코드와 주석등이 작성된 파일을 생성해주는 기능이 있습니다.
기본 안드로이드'파일생성 템플릿'외에 자신의 프로젝트구조나 스타일에 맞게 사용하고 싶은 '커스텀 템플릿'을 직접 플러그인형태로 추가 개발하여서, 아주 쉽게(?) 프로젝트에 사용할 수 있습니다.
(직접 만든 플러그인을 Intellij Plugin MarketPlace에 배포 및 공유도 가능합니다.)

Project Guide

  1. 프로젝트 환경 준비
  • Intellij IDE Plugin 개발환경은 레퍼런스 문서를 보니 3가지 유형이 있었습니다.

    1) IntelliJ Platform Plugin Template
    2) Building Plugins with Gradle
    3) Using DevKit

    이중에 IntelliJ Platform Plugin Template 프로젝트로 플러그인 개발 환경을 선택하였고, 다음과 같이 Github의 Use This Template를 사용하여 프로젝트 리포지토리를 생성하고 Android Studio에서 Clone(다운로드)합니다.

    (1) Use This Template - IntelliJ Platform Plugin Tempalte in Github

    (2) Clone from Github My Repository in Android Studio

  1. 프로젝트 구조
    .
    ├── .github/                GitHub Actions workflows and Dependabot configuration files
    ├── .run/                   Predefined Run/Debug Configurations
    ├── gradle
    │   └── wrapper/            Gradle Wrapper
    ├── build/                  Output build directory
    ├── src                     Plugin sources
    │   └── main
    │       ├── kotlin/         Kotlin source files
    │       └── resources/      Resources - plugin.xml, icons, messages
    │   └── test
    │       ├── kotlin/         Kotlin test files
    │       └── testData/       Test data used by tests
    ├── .gitignore              Git ignoring rules
    ├── build.gradle.kts        Gradle configuration
    ├── CHANGELOG.md            Full change history
    ├── gradle.properties       Gradle configuration properties
    ├── gradlew                 *nix Gradle Wrapper binary
    ├── gradlew.bat             Windows Gradle Wrapper binary
    ├── LICENSE                 License, MIT by default
    ├── qodana.yml              Qodana configuration file
    ├── README.md               README
    └── settings.gradle.kts     Gradle project settings
  1. 안드로이드용 커스텀 템플릿 플러그인 설정
    (1) gradle.properties
        # IntelliJ Platform Artifacts Repositories
        # -> https://plugins.jetbrains.com/docs/intellij/intellij-artifacts.html
        
        pluginGroup = com.github.ridsync.androidmvvmtemplate
        pluginName = android-mvvm-devoks-plugin  # 플러그인 명
        pluginVersion = 0.7.0 # 플러그인 버젼
        
        # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
        # for insight into build numbers and IntelliJ Platform versions.
        pluginSinceBuild = 203
        pluginUntilBuild = 212.*
        
        # Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl
        # See https://jb.gg/intellij-platform-builds-list for available build versions.
        pluginVerifierIdeVersions = 2020.3.4, 2021.1.3, 2021.2.1
        
        platformType = IC # 플랫폼 유형(커뮤니티,Ultimate,PhpStorm등의 타입선언)
        platformVersion = 2020.3.4  # IDE 플랫폼 버젼 (중요)
        platformDownloadSources = false
        
        # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
        # Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
        platformPlugins = android, org.jetbrains.android, org.jetbrains.kotlin, java, com.intellij.java
        
        # Java language level used to compile sources and to generate the files for - Java 11 is required since 2020.3
        javaVersion = 11
        
        gradleVersion = 7.2
        
        # Opt-out flag for bundling Kotlin standard library.
        # See https://plugins.jetbrains.com/docs/intellij/kotlin.html#kotlin-standard-library for details.
        # suppress inspection "UnusedProperty"
        kotlin.stdlib.default.dependency = false
        
        # 스튜디오 설치 경로 속성(in MacOS)
        StudioCompilePath = /Applications/Android Studio.app/Contents
        StudioRunPath = /Applications/Android Studio.app/Contents

(2) build.gradle.kts (기본 옵션에 추가된 빌드설정 요약.)

        intellij {
            ```
        		// localPath 설정 (안드로이드 스튜디오 경로)
            localPath.set(properties("StudioRunPath"))
        }
        
        tasks {
          ```
        	instrumentCode {
                compilerVersion.set("203.7717.56") // 현재 사용중인 Android Studio Version
            }
        }
        
        ```
        // 기타 patch, Signing, Publishing등의 옵션

(3) src/main/resource/META-INF/plugin.xml

        <!-- Plugin Configuration File. Read more: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->
        <idea-plugin>
            <id>androidmvvmtemplate</id>
            <name>android-mvvm-plugin-template</name>
            <vendor>ridsync</vendor>
        
            <depends>org.jetbrains.android</depends>
            <depends>com.intellij.modules.androidstudio</depends>
        
            <extensions defaultExtensionNs="com.android.tools.idea.wizard.template">
                <wizardTemplateProvider implementation="com.github.ridsync.wizard.WizardTemplateProviderImpl" />
            </extensions>
        <!-- 아래 클래스들은 불필요해서 주석처리 함 (미사용) -->
        <!--    <extensions defaultExtensionNs="com.intellij">-->
        <!--        <applicationService serviceImplementation="com.github.ridsync.androidmvvmtemplate.services.MyApplicationService"/>-->
        <!--        <projectService serviceImplementation="com.github.ridsync.androidmvvmtemplate.services.MyProjectService"/>-->
        <!--    </extensions>-->
        
        <!--    <applicationListeners>-->
        <!--        <listener class="com.github.ridsync.androidmvvmtemplate.listeners.MyProjectManagerListener"-->
        <!--            topic="com.intellij.openapi.project.ProjectManagerListener"/>-->
        <!--    </applicationListeners>-->
        
        </idea-plugin>

(4) src/main/kotlin/.../WizardTemplateProviderImpl.kt

        class WizardTemplateProviderImpl  : WizardTemplateProvider() {
        		// 템플릿 프로바이더 구현 클래스 - 직접 커스텀한 템플릿(mvvmWizardTemplate.Class)를 생성 및 반환하는 역할 
            override fun getTemplates(): List<Template> = listOf(mvvmWizardTemplate)
        }

(5) src/main/kotlin/.../mvvmWizardTemplate.kt

        // TemplateBuilder를 통해 실제 Custom Template의 UI,위젯,파일처리등을 정의하는 클래스
        
        name = "Android MVVM Creator (Project)"
        description = "Creates a new Fragment/ViewModel with layout file."
        minApi = MIN_SDK
        category = Category.Other // Check other categories
        formFactor = FormFactor.Mobile

(6) src/main/kotlin/.../mvvmWizardRecipe.kt

        // 파람을 통해 전달받은 ModuleTemplateData의 File정보로 
        // 최종 생성할 파일의 저장위치,파일명등을 정의 및 생성처리하는 클래스
        
        val (projectData, srcOut, resOut) = moduleData
        
            addAllKotlinDependencies(moduleData)
            val format = SimpleDateFormat("yyyy/MM/dd")
            val date = format.format(Date())
        
            val path = srcOut.absolutePath.replace("java","kotlin") // 현 프로젝트에서는 kotlin dir을 사용하므로 replace처리 함.
            val srcKotlinDir = File(path)
            // Fragment Template String Save
            save(
                someFragment(date, defaultPackage, newFilePackage, entityName, layoutName, projectData),
                srcKotlinDir.resolve("${entityName}Fragment.kt")
            )
            // ViewModel Template String Save
            save(someFragmentViewModel(date, defaultPackage, newFilePackage, entityName, layoutName, projectData),
                srcKotlinDir.resolve("${entityName}ViewModel.kt"))
            // Layout(XML) Template String Save
            save(someFragmentLayout(defaultPackage, newFilePackage, entityName),
                resOut.resolve("layout/$layoutName.xml")
            )

(7) src/main/kotlin/.../FragmentAndLayout.kt

        // 실제 생성할 파일들의 코드(String)를 생성하는 각 메소드 
        fun someFragment(
                date: String,
                defaultPackage: String,
                newFilePackage: String,
                entityName: String,
                layoutName: String,
                projectData: ProjectTemplateData
        ): String {
                val databindingName = "Fragment${entityName.toLowerCase().toCamelCase()}Binding"
                return """package $newFilePackage
                
        import android.os.Bundle
        import android.view.View
        import androidx.fragment.app.viewModels
        import dagger.hilt.android.AndroidEntryPoint
        import ${defaultPackage}.presentation.base.BaseAppBarFragment
        import ${defaultPackage}.databinding.${databindingName}
        import ${defaultPackage}.R
        
        /**
         * Created by user on ${date}.
         * Description :
         */
        @AndroidEntryPoint
        class ${entityName}Fragment : BaseAppBarFragment<${databindingName}>(R.layout.${layoutName.toLowerCase()}) {
        
            private val viewModel by viewModels<${entityName}ViewModel>()
        
            override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
                binding.fragment = this
                binding.viewModel = viewModel
                super.onViewCreated(view, savedInstanceState)
            }
        
            override fun onInitViews() {}
            override fun onSubscribeVm() {}
            override fun onSetToolBarViews() {}
        
        }
        
        """
        }
  1. 빌드 및 테스트

    • IDE를 직접 디버깅상태로 직접 띄워서 플로그인의 기능 및 UI를 테스트할 수 있다.

  2. 플러그인 설치 (jar)

    • 빌드 하면 /build/lib/ 폴더에 'android-mvvm-devoks-plugin-0.7.0.jar' 파일 생성 됨
    • Android Studio에서 Preferences > Plugins > Install Plugin from Disk...를 선택
    • 빌드하여 생성된 jar 파일을 선택하여 설치 완료.

  3. 플러그인 사용

    1. File > New > Other > Android MVVM Creator 를 선택
    2. Package는 자동완성 , EntitiyName을 작성하고,File Location을 선택
    3. Finish 버튼 선택하면 파일 생성 완료.

Wrap Up

안드로이드 스튜디오 타겟 버젼을 맞추기 위한 템플릿 프로젝트의 초기 환경설정시에 프로젝트 빌드가 안되는 현상이 발생하였습니다. 그래서 Github Issue에서 오류 로그를 찾아 확인해보니, instrunmentCode의 옵션을 추가하여 해당 플랫폼 버젼에 맞는 리포지토리로부터 libarary 다운로드받고 나서야 빌드가 정상적으로 진행되었습니다.
(참고: https://github.com/JetBrains/gradle-intellij-plugin/issues/369#issuecomment-893311439 )

플러그인을 통한 파일 생성시마다, 파일생성은 문제없으나 Gradle Sync가 동작하는 현상이 조금 있기는 한데 원인은 잘 모르겠습니다; (정상은 아닌듯...),

추가적으로, 선택한 프롬프트(?)의 폴더위치로 파일생성 경로를 자동 입력되게 하는 방법도 좋을것 같아서, File Template 관련 레퍼런스 문서가 추가되면 개선 해보려고 합니다.
그리고, 시간이 된다면, 마켓플레이스에 개발자가 쓸만한 멋진 플러그인을 한번 만들고 배포해보면 좋겠습니다.

Completion

Sample Source


https://github.com/ridsync/android-mvvm-devoks-plugin

Reference


https://plugins.jetbrains.com/docs/intellij/welcome.html

https://github.com/JetBrains/gradle-intellij-plugin

https://steewsc.medium.com/template-plugin-for-android-studio-4-1-92dcbc689d39

profile
[Android] Software Engineer

0개의 댓글