MoTLab -Mobility Technologies Engineering Blog-MoTLab -Mobility Technologies Engineering Blog-

Flutter moduleのAARをMaven + GitHub ActionsでGitHub Packagesにデプロイする

AndroidFlutter
November 17, 2022

Mobility TechnologiesでFlutterエンジニアとして働いているTomiと申します。

今回AndroidアプリケーションにFlutterを組み込む方法について調べてみました。調査した内容の中でFlutter moduleのAAR(Android ARchive)をMavenとGitHub Actionsを利用してGitHub Packagesにデプロイする方法を解説します。


はじめに


既存のAndroidアプリケーションからFlutter moduleを使うためには2つ方法があります。

この2つの方法の中で「Flutterのコードをビルドし、Android Archive(AAR)を出力し、そのAARをNative側に取り込む」ことにしました。

理由は下記の2点です。

  • Native側の開発は、毎回Flutter部分をビルドしなくても良いのでビルドが早いです。
  • FlutterエンジニアではないAndroidエンジニアがプロジェクトに参加する場合、Flutter側の環境構築する必要がないです。

公式ドキュメントにはローカル上の構築方法しか書かれていませんが、実際に運用するのであればCIを用いてリモートにデプロイすると思います。この記事はリモートにあるレポジトリ(GitHub Package)にMavenとGitHub Actionを使ってデプロイする方法を解説します。

注意点


GitHub PackageにMavenを利用してデプロイする方法は、Flutter v3.3.0でバグが有り、それはv3.5.0で対応予定になります。

流れ


  1. AARを作成する
  2. MavenでGitHub Packagesにデプロイする
  3. GitHub Actionを使ってデプロイを自動化する

AARを作成する


Flutter moduleをAndroidアプリケーションに組み込むためにAARファイルを作成します。

flutter build aar

上のコマンドでAARを生成するとバージョンは1.0になります。 pubspec.yamlにバージョンを指定してもAARファイルには反映されません。バージョンを変更したい場合は--build-numberオプションを使ってください。

flutter build aar --build-number 2.0.0

上のコマンドで実行すると/build/host/outputs/repoに下記が生成されます。

.
└── com
    └── example
        └── moduletest
            ├── flutter_debug
            │   ├── 2.0.0
            │   │   ├── flutter_debug-2.0.0.aar
            │   │   ├── flutter_debug-2.0.0.aar.md5
            │   │   ├── flutter_debug-2.0.0.aar.sha1
            │   │   ├── flutter_debug-2.0.0.pom
            │   │   ├── flutter_debug-2.0.0.pom.md5
            │   │   └── flutter_debug-2.0.0.pom.sha1
            │   ├── maven-metadata.xml
            │   ├── maven-metadata.xml.md5
            │   └── maven-metadata.xml.sha1
            ├── flutter_profile
            │   ├── 2.0.0
            │   │   ├── flutter_profile-2.0.0.aar
            │   │   ├── flutter_profile-2.0.0.aar.md5
            │   │   ├── flutter_profile-2.0.0.aar.sha1
            │   │   ├── flutter_profile-2.0.0.pom
            │   │   ├── flutter_profile-2.0.0.pom.md5
            │   │   └── flutter_profile-2.0.0.pom.sha1
            │   ├── maven-metadata.xml
            │   ├── maven-metadata.xml.md5
            │   └── maven-metadata.xml.sha1
            └── flutter_release
                ├── 2.0.0
                │   ├── flutter_release-2.0.0.aar
                │   ├── flutter_release-2.0.0.aar.md5
                │   ├── flutter_release-2.0.0.aar.sha1
                │   ├── flutter_release-2.0.0.pom
                │   ├── flutter_release-2.0.0.pom.md5
                │   └── flutter_release-2.0.0.pom.sha1
                ├── maven-metadata.xml
                ├── maven-metadata.xml.md5
                └── maven-metadata.xml.sha1

これでGithub Packagesにデプロイする準備できました。

💡
上のファイルtreeを見るとAARファイルが3つしかありませんが、Flutter module内で他のライブラリ(Google Mapなど)を使用するすると、増える場合があります。

MavenでGitHub Packagesにデプロイする


GitHub PackagesではMavenでデプロイする方法のドキュメントを提供しています。このドキュメントによると下記の3つを対応することでGitHub Packagesへのデプロイすることができます。

  1. ~/.m2/settings.xmlの設定する
  2. pomファイルdistributionManagementタグを利用してリモートリポジトリの情報を追加する
  3. mvn deployコマンドを実行する

2に関して問題点があります。flutter build aarpomファイルが複数自動生成されますが、ビルドごとに上書きされるため、ひとつづつdistributionManagementを追加することは難しいです。

自動生成されたAARファイルpomファイルが同じ層に1:1になってるのが解決の糸口になりました。

...省略
            ├── flutter_debug
            │   ├── 2.0.0
            │   │   ├── flutter_debug-2.0.0.aar
            │   │   ├── flutter_debug-2.0.0.aar.md5
            │   │   ├── flutter_debug-2.0.0.aar.sha1
            │   │   ├── flutter_debug-2.0.0.pom
            │   │   ├── flutter_debug-2.0.0.pom.md5
            │   │   └── flutter_debug-2.0.0.pom.sha1
...省略

この問題は、mvn deploy:deploy-fileコマンドにURLオプションでGitHubレポジトリの指定をすることで解決できます。

pomファイルリストを探す

正常に作動させるためには全てのAARファイルpomファイルをデプロイする必要があり、findコマンドを利用してpomファイルを検索しました。

find . -name "*.pom" -type f -print0 | xargs -I{} -0

上のコマンドの実行結果が下記です。

./com/example/moduletest/flutter_profile/2.0.0/flutter_profile-2.0.0.pom
./com/example/moduletest/flutter_debug/2.0.0/flutter_debug-2.0.0.pom
./com/example/moduletest/flutter_release/2.0.0/flutter_release-2.0.0.pom

Mavenを利用してデプロイする

上記の「pomファイルリストを探す」で用いたコマンドを利用し、Mavenコマンドでデプロイします。

find . -name "*.pom" -type f -print0 | xargs -I{} -0 bash -c 'mvn -B deploy:deploy-file -Durl="https://maven.pkg.github.com/{owner}/{repository name}" -DrepositoryId=github -Dtoken=${{ secrets.GITHUB_TOKEN }} -DpomFile="$0" -Dfile="${0%.pom}.aar"' '{}' \;
  • GitHub Packageはhttps://maven.pkg.github.com/{owner}/{repository name}ような形でURLを設定する必要があります。
  • GitHub Actionsの利用を想定しているので、secrets.GITHUB_TOKENを利用していますが、それ以外のCIを利用する場合は、ここをGitHubのPersonal Access Tokenで置き換えてください。

しかしこのままでは認証エラーが発生します。

Settings.xmlファイルを設定して認証エラーを回避する

元々mavenでGitHub Packagesにデプロイする時には~/.m2/settings.xmlファイルを設定する必要がありますsettings.xml設定してないので認証エラーが発生しました。

解決方法はmvnコマンドの-sオプションを使ってsettings.xmlを指定することです。

settings.xmlを作成します。

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <servers>
        <server>
            <id>github</id>
            <username>Mobility Technologies</username>
            <password>${env.GITHUB_TOKEN}</password>
        </server>
    </servers>
</settings>
  • env.GITHUB_TOKEN では後でGithub Actionsのyamlファイルで指定する予定です。

下のコマンドはmvnコマンドの-sオプションを使ってsettings.xmlを指定しました

find . -name "*.pom" -type f -print0 | xargs -I{} -0 bash -c 'mvn -B -s settings.xml deploy:deploy-file -Durl="https://maven.pkg.github.com/{owner}/{repository name}" -DrepositoryId=github -Dtoken=${{ secrets.GITHUB_TOKEN }} -DpomFile="$0" -Dfile="${0%.pom}.aar"' '{}' \;

上のコマンドを実行するとGithub Packagesにデプロイできると思います。

GitHub Actionsを使ってデプロイを自動化する


💡
基本的なGitHub Actionsの設定方法はこちらを参照してください。

今まで説明したコマンドをGitHub Actionsのyamlファイルに追加すれば終わりですが、先にバージョンをどのように指定するか考える必要があります。

バージョンを指定してAARファイルをビルドする

...省略
on:
  push:
    tags:
      - '[1-9].[0-9]+.[0-9]+'
...省略

- name: build aar
  run: |
    flutter build aar --build-number=$(echo $GITHUB_REF | cut -d / -f 3)

GitHub Actionsのyamlファイル上で上記のように設定するとバージョン設定が可能ですが、1つずつ解説いたします。

on:
  push:
    tags:
      - '[1-9].[0-9]+.[0-9]+'

tagをpushすると、それがトリガーとなり、このWorkflowが走ります。

echo $GITHUB_REF | cut -d / -f 3

tag2.0.0で指定した場合、GitHubのcontext変数ref($GITHUB_REF)では”refs/tags/2.0.0" が入ってきますが、echocutを利用してバージョンだけ抽出します。

上記のechoを実行すると”2.0.0”が抽出されます。

この”2.0.0”を使ってaarファイルをビルドします。

- name: build aar
  run: |
    flutter build aar --build-number=$(echo $GITHUB_REF | cut -d / -f 3)

これでtagの名前を2.0.0にした場合、2.0.0バージョンでビルドされてAARファイルpomファイルが生成されます。

デプロイする

- name: mvn deploy
  run: |
    find . -name "*.pom" -type f -print0 | xargs -I{} -0 bash -c 'mvn -B -s settings.xml deploy:deploy-file -Durl="https://maven.pkg.github.com/{owner}/{repository name}" -DrepositoryId=github -Dtoken=${{ secrets.GITHUB_TOKEN }} -DpomFile="$0" -Dfile="${0%.pom}.aar"' '{}' \;
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

上のアクションで該当するGitHubレポジトリにデプロイすることが可能です。

env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

上の部分は前述したsettings.xmlで使う環境変数です。

全体コード


Flutter Project Path/settings.xml

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <servers>
        <server>
            <id>github</id>
            <username>Mobility Technologies</username>
            <password>${env.GITHUB_TOKEN}</password>
        </server>
    </servers>
</settings>

Flutter Project Path/.github/workflows/push-tag-deploy.yml

name: push tag deploy

on:
  push:
    tags:
      - '[1-9].[0-9]+.[0-9]+'

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    permissions:
      contents: read
      packages: write

    steps:
    - name: Get the version
      id: get_version
      run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)

    - name: Checkout code
      uses: actions/checkout@v3

    - name: flutter action
      uses: subosito/flutter-action@v2
      with:
        flutter-version: '3.0.5'

    - name: Add path
      run: echo "$(pwd)/flutter/bin" >> $GITHUB_PATH

    - name: Get dependencies
      run: flutter pub get

    - name: build aar
      run: |
        flutter build aar --build-number=${{ steps.get_version.outputs.VERSION }}

    - name: mvn deploy
      run: |
        find . -name "*.pom" -type f -print0 | xargs -I{} -0 bash -c 'mvn -B deploy:deploy-file -Durl="https://maven.pkg.github.com/{owner}/{repository name}" -DrepositoryId=github -Dtoken=${{ secrets.GITHUB_TOKEN }} -DpomFile="$0" -Dfile="${0%.pom}.aar"' '{}' \;
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Android Project Path/build.gradle

allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url "$storageUrl/download.flutter.io" }
        maven {
            name = "GitHubPackages"
            url = uri("https://maven.pkg.github.com//{owner}/{repository name}")
            credentials {
                username = User Name
                password = Personal Access Token
            }
        }
    }
}

Android Project Path/app/build.gradle

dependencies {
  debugImplementation 'com.example.app:flutter_debug:2.0.0'
  profileImplementation 'com.example.app:flutter_profile:2.0.0'
  releaseImplementation 'com.example.app:flutter_release:2.0.0'
}

おわり


頑張ってGitHub Packagesにデプロイすることを成功させましたが、2日後にFlutter v3.3.0 発表され、いきなりデプロイできなくなってしまいました。その時、バージョンの影響に受けない方法を探す必要があるかと思いまして、GitHub Packagesを使わずGitHub Repositoryに/build/host/outputs/repoをそのままpushしておいてAndroid側でraw.githubusercontent.com を使って依存性を取得するような方法で変更しました。

この方法は別の記事で扱ってみようかと思います。


We're Hiring!

📢
Mobility Technologies ではともに働くエンジニアを募集しています。

興味のある方は 採用ページ も見ていただけると嬉しいです。

Twitter @mot_techtalk のフォローもよろしくお願いします!