Continuity is The Father of Success

Androidアプリとかゲームとか。毎日続けてるものについて。

Flutter Meetup #7 に参加してきました

あったこと

Flutter Meetup Tokyoにまた5分LT枠で参加してきました。

flutter-jp.connpass.com

LT資料はこちら。

speakerdeck.com

会場はメルカリさんでした。六本木ヒルズ高いなーという気分と、入り口の警備がやっぱり厳重だなーという感想。 写真撮るの忘れちゃいましたが、会場もあらかた埋まっていて盛況な感じを受けました。

LT内容の説明

2018年10月31日のブログの内容をベースに、Flutter内のAndroidプロジェクトでAndroid Gradle pluginの更新をやりすぎると、偶にビルドができなくなる問題について紹介しました。 こちらはstable版がリリースれた現在でも(むしろbeta版やdev版を触らなくなった今だからこそ)気に留めておく必要がある気がしています。

dr1009.hatenablog.com

flutter build apk コマンドを叩いた時、Flutter SDKの内部では次の順にクラスが呼び出されていきます。

  1. {flutter sdk root}/packages/flutter_tools/lib/src/commands/build_apk.dart
  2. {flutter sdk root}/packages/flutter_tools/lib/src/android/apk.dart
  3. {flutter sdk root}/packages/flutter_tools/lib/src/android/gradle.dart

最後のステップでAndroid project側のGradleに処理が引き渡されていきます。 このことにより、AndroidのプロジェクトのビルドではDartを用いながらも、処理の大半をGradleのビルド処理として綺麗に対応しています。

github.com

今回問題となるのは {flutter sdk root}/packages/flutter_tools/gradle/flutter.gradle です。 こちらは、flutterで作られたプロジェクトのandroid/app/build.gradle 内で読み込まれています。

サンプルプロジェクトを作ってみると、下記の感じです。

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
    flutterVersionCode = '1'
}

def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
    flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" <= ココ

{flutter sdk root}/packages/flutter_tools/gradle/flutter.gradle の内部を確認してみると、Android Gradle pluginのバージョン指定をした上で読み込みを行なっています。

github.com

import java.nio.file.Path
import java.nio.file.Paths

import com.android.builder.model.AndroidProject
import org.apache.tools.ant.taskdefs.condition.Os
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.Task
import org.gradle.api.file.CopySpec
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.bundling.Jar

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'
    }
}

当時立っていたissueやその対応をみると、Android Gradle pluginだけではなく repositories の順序を入れ替えています。 これは 3.1.2 から 3.2.1 への変更によるBuild失敗が、読み込みにいくRepositoryの修正によるものだったためです。

得られる知見

Flutter SDK の更新と AndroidStudio の更新は一致しません。 FlutterはFlutterの都合で開発されますし、AndroidAndroidの都合で開発されるという当たり前の話です。

ただ、こういった事情が FlutterプロジェクトAndroidプロジェクト に合わせて更新しようとした際、問題を引き起こすことがあります。 今回のケースとは逆に、 Flutter SDK の更新と同時にAndroid Gradle pluginの更新が必要になるケースも発生するかもしれません。 これらのことを踏まえて、FlutterAndroid、そして iOS (iOSのコマンドはまだうまく読めていないので省略します。。。)の更新をつぶさに追っていく必要があると言えます。

終わりに

MeetupではCIの話やビルドの話などをメインで進めてしまったので、次はもう少しコードよりのLTがしたいなーと思っています!