🔥

ビルド成功するまでが遠すぎる。3年稼働したアプリのFlutterバージョン変更がしんどかった話。

に公開

Flutter 2.17 → 3.4 バージョンアップ対応

はじめに

3年以上運用していたFlutterアプリで、XCodeのバージョンアップとAndroid TargetSDKの対応が必要になり、Flutter 2.17から3.4へのアップデート対応をしましたが、結構地獄だったので備忘録として残します。

対応が必要になった背景

技術的な要因

  • XCode 15対応: iOS 17対応のためにXCode 15が必要
  • Android TargetSDK 34対応: Google Play Consoleの要件

対応前の環境

# pubspec.yaml (対応前)
environment:
  sdk: ">=2.17.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  # 古いバージョンのプラグイン群
  firebase_core: ^1.24.0
  # その他多数のプラグイン...

対応後の環境

# pubspec.yaml (対応後)
environment:
  sdk: ">=3.4.0 <4.0.0"

dependencies:
  flutter:
    sdk: flutter
  # アップデートされたプラグイン群
  firebase_core: ^2.24.2
  # その他多数のプラグイン...

iOS対応で必要だった対応

Podfileの更新

# ios/Podfile
platform :ios, '12.0'  # 11.0から12.0に変更

# 新しく追加
install! 'cocoapods', :deterministic_uuids => false

target 'Runner' do
  use_frameworks!
  use_modular_headers!

  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

# 新しく追加
post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    
    # iOS 12.0対応
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
    end
  end
end

ビルドエラーの解決

# よく発生したエラーと解決方法
cd ios
pod deintegrate
pod cache clean --all
rm Podfile.lock
pod install

Android対応の地獄

build.gradleの大幅変更

// android/app/build.gradle
android {
    compileSdkVersion 34  // 33から34に変更
    ndkVersion "25.1.8937393"  // 新しく追加

    defaultConfig {
        minSdkVersion 21    // 19から21に変更
        targetSdkVersion 34 // 33から34に変更
        multiDexEnabled true // 新しく追加
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    // 新しく追加
    namespace "com.example.myapp"
}

AndroidManifest.xmlの変更

<!-- android/app/src/main/AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">  <!-- 削除が必要 -->

<application
    android:label="MyApp"
    android:name="${applicationName}"
    android:icon="@mipmap/ic_launcher"
    android:usesCleartextTraffic="true">  <!-- 新しく追加 -->

</application>

gradle.propertiesの更新

# android/gradle.properties
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true

# 新しく追加
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false

プラグイン対応

プラグインのバージョン互換性問題

# 対応が必要だったプラグイン例
dependencies:
  # Firebase関連
  firebase_core: ^1.24.0 → ^2.24.2
  
  # 画像関連
  image_picker: ^0.8.7+5 → ^1.0.4
  
  # 状態管理
  provider: ^6.0.5 → ^6.1.1
  
  # その他
  http: ^0.13.5 → ^1.1.0
  shared_preferences: ^2.0.18 → ^2.2.2

プラグインの破壊的変更対応

// 古いコード
import 'package:http/http.dart' as http;

Future<void> fetchData() async {
  final response = await http.get('https://api.example.com/data');
  // ...
}

// 新しいコード
import 'package:http/http.dart' as http;

Future<void> fetchData() async {
  final response = await http.get(Uri.parse('https://api.example.com/data'));
  // Uri.parse()が必要になった
}

非推奨APIの対応

// 古いコード
Widget build(BuildContext context) {
  return MaterialApp(
    title: 'My App',
    theme: ThemeData(
      primarySwatch: Colors.blue, // 非推奨
    ),
  );
}

// 新しいコード
Widget build(BuildContext context) {
  return MaterialApp(
    title: 'My App',
    theme: ThemeData(
      colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
    ),
  );
}

まとめ

多分新しくプロジェクト作って、flutter部分のコードだけ移植した方が早いしラクそう。

ミスもあるかもしれませんが、次にアップデート対応をする人に少しでもお役に立てたら嬉しいです。

株式会社アクトビ

Discussion