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点です。
公式ドキュメントにはローカル上の構築方法しか書かれていませんが、実際に運用するのであればCIを用いてリモートにデプロイすると思います。この記事はリモートにあるレポジトリ(GitHub Package)にMavenとGitHub Actionを使ってデプロイする方法を解説します。
GitHub PackageにMavenを利用してデプロイする方法は、Flutter v3.3.0でバグが有り、それはv3.5.0で対応予定になります。
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にデプロイする準備できました。
GitHub PackagesではMavenでデプロイする方法のドキュメントを提供しています。このドキュメントによると下記の3つを対応することでGitHub Packagesへのデプロイすることができます。
2に関して問題点があります。flutter build aarでpomファイルが複数自動生成されますが、ビルドごとに上書きされるため、ひとつづつ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レポジトリの指定をすることで解決できます。
正常に作動させるためには全ての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
上記の「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"' '{}' \;
しかしこのままでは認証エラーが発生します。
元々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>
下のコマンドは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のyamlファイルに追加すれば終わりですが、先にバージョンをどのように指定するか考える必要があります。
...省略
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
tagを2.0.0で指定した場合、GitHubのcontext変数ref($GITHUB_REF)では”refs/tags/2.0.0" が入ってきますが、echoとcutを利用してバージョンだけ抽出します。
上記の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 を使って依存性を取得するような方法で変更しました。
この方法は別の記事で扱ってみようかと思います。
興味のある方は 採用ページ も見ていただけると嬉しいです。
Twitter @mot_techtalk のフォローもよろしくお願いします!