본문으로 바로가기

(https://flutter-ko.dev/docs/deployment/android) (한국어)
(https://flutter.dev/docs/deployment/android) (영어)
(https://here4you.tistory.com/198) 잘 설명한 한국어 블로그

 

Android 앱 출시 준비하기

Flutter 앱을 개발하는 동안, 커멘드 라인에서의 `flutter run`을 실행하거나IDE에 있는 툴바 **Run** 과 **Debug**를 선택하여 앱을 테스트할 수 있습니다. Flutter는 기본적으로 앱의 _debug_ 버전을 빌드합니�

flutter-ko.dev

 

Adding a launcher icon

번역할 필요 없이 간단하게 아래 포스트로 해결합시다.

 

https://darrengwon.tistory.com/375

 

앱 아이콘 변경하기

https://appicon.co/ App Icon Generator Generate icons and images for mobile apps, android and iOS. No need to upload or download. Works on your browser appicon.co flutter에서 앱 아이콘을 변경하기 위..

darrengwon.tistory.com

 

Signing the app

 

앱 서명을 합니다.

keytool -genkey -v -keystore c:/Users/[사용자 이름]/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key

keytool -genkey -v -keystore c:/Users/BOSSMONSTER/key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key

 

keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect
이 오류는 user.home 디렉토리 내에 이미 .keystore 파일이 생성되어 있는 경우 발생 합니다.
그러므로 폴더에서 이 파일을 삭제한 후 keytool 명령을 다시 실행하십시오.

 

오률 뚫고 난 후 해당 폴더(user.home)를 살펴보면 정상적으로 서명이 생성된 것을 볼 수 있습니다. 생성 도중 요구하는 비밀번호를 적어놓도록 합시다.

 

 

이 생성된 키는 지정한 경로인 c:/Users/BOSSMONSTER 에 저장이 됩니다. 이 키를 android/app의 경로에 넣어줍시다.

 

(나중에 앱 출시할 때 디버그 서명키를 사용했다고 오류가 뜬다면 혹시 key.jks를 앱을 구성하는 단계가 아니라 C 같이 그냥 로컬하게 넣은 것이 아닌지 확인하십시오)

 

Reference the keystore from the app

 

Create a file named <app dir>/android/key.properties that contains a reference to your keystore:

 

android 폴더에 key.properties 파일을 생성한 후 다음 내용을 적어줍시다. 경로는 앞서 서명했을 때 key.jks를 가지고 있는 경로를 설정해주면 됩니다.

 

storePassword=<password from previous step>
keyPassword=<password from previous step>
keyAlias=key
storeFile=<location of the key store file>

경로의 기본은 android/app입니다. 생성한 키를 어디에 저장했는지를 지정해주면 됩니다. 

storePassword=<키생성시 입력한 암호>
keyPassword=<키생성시 입력한 암호>
keyAlias=key
storeFile=./key.jks

 

 

 

Configure signing in gradle

 

Configure signing for your app by editing the <app dir>/android/app/build.gradle file.

 

1.

/android/app/build.gradle 에 가서 android {...} 코드의 바로 전에 다음 내용을 추가해주면 됩니다.

 

안드로이드 설정을 담은 코드 위 부분에 넣어주면 됩니다. 첨부한 그림 상에서는 27번 째 줄이겠군요.

 

   def keystoreProperties = new Properties()
   def keystorePropertiesFile = rootProject.file('key.properties')
   if (keystorePropertiesFile.exists()) {
       keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
   }

   android {
         ...
   }

 

 

 

2.

Add code before buildTypes block:

 

아래 코드 블럭을 추가하고, buildTypes도 release로 변경합니다.

   signingConfigs {
       release {
           keyAlias keystoreProperties['keyAlias']
           keyPassword keystoreProperties['keyPassword']
           storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
           storePassword keystoreProperties['storePassword']
       }
   }
   buildTypes {
       release {
           // signingConfigs.debug 에서 release로 변경합니다.
           signingConfig signingConfigs.release
       }
   }

 

이제 배포용으로 빌드합니다. 이미 빌드한 게 말썽을 부린다면 clean으로 기존 빌드를 제거해줍시다.

flutter clean
flutter run --release

 

빌드 시 종종 Using hardware rendering with device Android SDK built for x86. If you get graphics artifacts, consider enabling software rendering with "--enable-software-rendering". 오류가 납니다. 에뮬레이터가 아니라 실제 기기를 사용합시다.

 

빌드가 성공했다면 자동으로 서명 키가 주입된 것입니다.

 

빌드 성공 결과는 다음과 같습니다.

 

앱 축소, 난독화 및 최적화를 위한 with R8 / Proguard 사용

 

(https://developer.android.com/studio/build/shrink-code)

 

앱 축소, 난독화 및 최적화  |  Android 개발자  |  Android Developers

사용하지 않는 코드와 리소스를 삭제하기 위해 출시 빌드에서 코드를 축소하는 방법을 알아보세요.

developer.android.com

기본적으로, Flutter는 Android 관련 코드를 난독화하거나 축소화하지 않습니다. 서드파티 자바 라이브러리나 Android 라이브러리를 사용한다면 Proguard 적용 혹은 R8 을 통해 APK의 크기를 줄이고 리버스 엔지니어링으로부터 코드를 보호할 수 있습니다.

 

Proguard의 개선책으로 구글이 R8을 만들었습니다만, 아직 한국에는 자료가 별로 없습니다. 아직 한국어판에는 번역이 되지 않았습니다. R8에 대해서 한국어로 번역된 다른 문서를 참고해보니, "R8은 기존의 모든 ProGuard 규칙 파일과 호환되므로 R8을 사용하도록 Android Gradle 플러그인을 업데이트하면 기존 규칙을 변경할 필요가 없습니다." 라고 합니다.

 

Line 에서도 19년 12월 말 경에야 도입한 것으로 확인되었습니다. R8 사용자가 많아지면 그 때 R8을 사용하기로 하고, 우선은 Progurad를 사용해보겠습니다.

 

 

Proguard Rule을 구성하기 위해 /android/app/proguard-rules.pro 파일을 생성하고 다음과 규칙을 추가한다.

## Flutter wrapper
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.**  { *; }
-keep class io.flutter.util.**  { *; }
-keep class io.flutter.view.**  { *; }
-keep class io.flutter.**  { *; }
-keep class io.flutter.plugins.**  { *; }
-dontwarn io.flutter.embedding.**

 

 

Gradle 빌드시 proguard-rules.pro 파일을 참조하여 코드 난독화와 사이즈를 축소할 수 있도록 /android/app/build.gradle 파일의 buildTypes 블럭안에 다음의 내용을 추가한다.

 

android {
    ...
    
    buildTypes {
        release {
            // release 속성으로 변경
            signingConfig signingConfigs.release

            // start of 코드난독화 및 사이즈 축소
            minifyEnabled true
            useProguard true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            // end of 코드난독화 및 사이즈 축소
        }
    }
}

 

 

 

* Proguard Rule 파일을 이용해서 위의 내용과 같이 build.gradel 파일을 설정한 후 배포용 앱을 빌드할 때 간혹 에러가 발생할 수 있다. 이는 Flutter 앱을 개발하면서 사용한 외부 패키지들의 난독화도중 에러가 발생하는 것으로 보여지는데 필자도 아직까지 해결하지 못하고 있다. 이경우 우선은 위의 코드난독화 및 사이즈 축소 설정을 주석으로 처리해서 빌드시 발생하는 에러를 회피할 수 있다.

 

Reviewing the app manifest

/android/app/src/main/AndroidManifest.xml 파일을 열어 앱의 최종 이름과 사용할 퍼미션을 설정한다.

 

applicationEdit the android:label in the application tag to reflect the final name of the app.

앱의 이름을 결정하라는 것입니다.

 

 

uses-permission Add the android.permission.INTERNET permission if your application code needs Internet access. The standard template does not include this tag but allows Internet access during development to enable communication between Flutter tools and a running app.

 

앱의 퍼미션을 설정합니다. 인터넷 접속이 필요하면 인터넷 퍼미션을 추가해줘야 합니다. 아래 코드를 보시면, 인터넷, 카메라, 챌린더 읽고 쓰기 등의 기능 퍼미션을 추가한 것을 볼 수 있습니다. 아마 geolation 패키지를 이용했을 때 이 부분을 만진 경험이 있을 것입니다. 그 때와 똑같이 해주면 됩니다.

 

 

Reviewing the build configuration

 

/android/app/build.gradle 파일을 열어 빌드 구성을 검토한다.

 

  • defaultConfig:

    • applicationId: 고유한 최종 (Application Id) appid를 지정하세요. (id는 한 번 게시된 이후에는 수정 불가)

    • versionCode & versionName: 내부 앱 버전 번호를 지정하고, 문자열 형태로 명시하세요. pubspec.yaml 파일에 version 속성을 설정하여 내부 앱 버전 번호를 문자열 형태로 지정할 수 있습니다. 버전 정보 지침에 대해서는 버전 문서를 참조하세요.

    • minSdkVersion & targetSdkVersion: 최소 API 레벨과 개발 대상 버전으로 지정한 지정 API 레벨을 명시하세요. 자세한 내용은 버전 문서의 API 레벨 영역을 참조하세요.

플러터는 16 이후 부터 지원해서 최소가 16 이상이다. 버전에 대해서는 아래 글을 참고하자.

(https://devlog.jwgo.kr/2019/12/17/what-version-of-sdk-do-i-choose-using-flutter/)

 

플러터(Flutter) 배포 시 어떤 버전의 안드로이드 SDK를 선택해야 할까. · Tonic

사이트 운영에 도움을 주실 수 있습니다. 고맙습니다. --> 플러터(Flutter) 배포 시 어떤 버전의 안드로이드 SDK를 선택해야 할까. 2019년 12월 17일 TL;DR 플러터 최소 지원 버전은 API 16, 그러나 사실 상

devlog.jwgo.kr

 

Building the app for release

 

You have two possible release formats when publishing to the Play Store.

  • App bundle (preferred) => APK보다 무거우나 온라인 테스트가 가능함!
  • APK

앱 번들로 빌딩하는 방법은 다음과 같다.

 

  1. cd <app dir>로 이동
  2. flutter build appbundle을 실행하세요.
    (flutter build 실행은 기본적으로 release 빌드 입니다.)
flutter build appbundle

 

 

위 경로에 가보면 앱 번들이 존재한다.

 

 

APK로 빌드하는 방법은 다음과 같다.

 

  1. cd <app dir>로 이동
  2. flutter build apk --split-per-abi 실행하세요
    (flutter build 실행은 기본적으로 release 빌드 입니다.)
flutter build apk --split-per-abi

 

 

그런데 앱 번들과 달리 APK는 타겟별로 3개나 빌드가 되었습니다.

 

 Built build\app\outputs\apk\release\app-armeabi-v7a-release.apk (5.5MB).

 Built build\app\outputs\apk\release\app-arm64-v8a-release.apk (5.8MB).

 Built build\app\outputs\apk\release\app-x86_64-release.apk (6.0MB).

 

* 참고로 2019년 8월 1일부터 Google Play에 앱을 게시할 때 32비트 버전 외에 64비트 버전도 함께 지원이 되어야하는 정책 때문입니다. 참고로 앱 스토어는 진작부터 64비트 버전만 지원하고 있습니다. 위 3개의 apk는 모두 64비트를 지원하는 apk 입니다.

 

 

APK를 빌드한 후 실제 기기에서 테스트하는 방법은 다음과 같습니다. 기기 이름을 모르겠다면 flutter install만 입력해도 실행 가능한 기기의 종류를 보여줍니다.

flutter install -d [기기 이름]

 

 

이제 구글 플레이에 배포해보겠습니다

 

구글 플레시 스토어 콘솔에 접속한 후 가입합니다. 가입 비용이 25$입니다.

 

https://developer.android.com/distribute?hl=ko

 

Google Play  |  Android Developers

전 세계에서 Android 앱 구매를 위해 가장 많이 방문하는 스토어입니다. 클라우드에 연결되어 있으며 항상 동기화되어 있습니다. 사용자가 손쉽게 앱을 찾고 다운로드할 수 있습니다.

developer.android.com

 

 

언어 설정, 설명, 홍보용 사진. 영상, 개발자 주소 등등을 업로드합시다. 

 

 

 

앱 등록을 마치면 APK나 앱 번들을 업로드해야 합니다. 무엇이 되었든 드래그 앤 드랍이면 됩니다. 오류가 생기면 무엇이 문제인지 말해주므로 해결합시다.

 

대표적인 오류)

 

1. 디버그 서명키로 빌드되었습니다. => release로 buildType 변경, 생성한 키를 프로젝트 내에 포함시켰는지, key.properties에 설정한 경로는 안 틀렸는지

 

2. 'com.example'이(가) 제한된 상태이므로 다른 패키지 이름을 사용해야 합니다. => 애초에 com.example을 설정하지 않고 코딩을 했어야 맞습니다. 이후 수정하려면 다음과 같은 과정을 거칩니다.

(https://stackoverflow.com/questions/51534616/how-to-change-package-name-in-flutter)

 

 

 

 

출시 버전은 1.0.0과 같이 semantic하게 작성합니다. 한 후에는 스토어 등록 정보, 콘텐츠 등급(성인물인가?) 등등을 모두 설정해줘야 스토어에 배포할 수 있게 됩니다. 번거롭지만 다 해줍시다.

 

무언가 미작성된 경우가 있으면 ✔ 위에 호버를 해주면 무엇인지 알려줍니다.

 

 

 

모두 작성한 이후에는 출시 버튼을 눌러 출시해줍시다.

 

 

 

구글 측에서 어플을 검토하는 중입니다. 검토가 되면 스토어에 올라갑니다.

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체