📋 今日の内容
ケーススタディ
ケース1:突然アプリが起動しなくなった
ケース2:ビルドは成功するのに真っ白画面
ケース3:Android版は動くのにiOS版が動かない
ケース4:本番ビルドだけエラーが出る
ケース5:パッケージ更新後に動かなくなった
実際の調査プロセス!
ケース1:突然アプリが起動しなくなった
状況:昨日まで動いていたアプリが、今日突然起動しない
エラーメッセージ:
flutter run
Launching lib/main.dart on sdk gphone64 arm64 in debug mode...
FAILURE: Build failed with an exception.
🔍 調査ステップ1:何が変わったか確認
- 昨日と今日で何か変えた?
-
何も変えていません…
でも実は:
- 他のプロジェクトで作業した
- Android Studioを更新した
- macOSを更新した
🔍 調査ステップ2:環境チェック
flutter doctor -v
```
**出力:**
```
[!] Android toolchain - develop for Android devices
✗ Android SDK file not found: ~/.android/debug.keystore
原因発見!debug.keystoreが消えている!
✅ 解決方法(段階的に試す)
# debug.keystoreを再生成
keytool -genkey -v -keystore ~/.android/debug.keystore \
-storepass android -alias androiddebugkey \
-keypass android -keyalg RSA -keysize 2048 -validity 10000
```
**質問に答える:**
```
姓名: test
組織単位: test
組織: test
都市: test
都道府県: test
国コード: JP
再実行:
flutter run
✅ 解決!
💡 学んだこと
ケース2:ビルドは成功するのに真っ白画面
flutter run
✓ Built build/app/outputs/flutter-apk/app-debug.apk
ビルド成功!でもアプリを開くと真っ白… 😱
🔍 調査ステップ1:ログを確認
# 詳細ログで実行
flutter run -v
```
**ログを見ると:**
```
E/flutter (12345): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)]
Unhandled Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
🔍 調査ステップ2:main.dart を確認
問題のコード:
void main() {
// SharedPreferences を初期化
SharedPreferences prefs = await SharedPreferences.getInstance();
runApp(MyApp());
}
エラー!
await を使っているのに async がない
WidgetsFlutterBinding.ensureInitialized() がない
✅ 解決方法(段階的に試す)
修正後:
void main() async { // async を追加
// Flutter の初期化を保証
WidgetsFlutterBinding.ensureInitialized(); // これを追加
// SharedPreferences を初期化
SharedPreferences prefs = await SharedPreferences.getInstance();
runApp(MyApp());
}
💡 学んだこと
ケース3:Android版は動くのにiOS版が動かない
Androidエミュレータ:✅ 完璧に動く
iOSシミュレータ:❌ 起動直後にクラッシュ
🔍 調査ステップ1:iOS特有の設定を確認
# iOSで実行
flutter run -d iPhone
# エラー:
[VERBOSE-2:platform_view_layer.cc] Trying to embed a platform view but the
PrerollContext does not support embedding
🔍 調査ステップ2:Info.plist を確認
問題:パーミッションの説明が抜けている
open ios/Runner/Info.plist
カメラを使っているのに:
open ios/Runner/Info.plist
✅ 解決方法
Info.plist に追加:
<?xml version="1.0" encoding="UTF-8"?>
<dict>
<!-- 既存の設定 -->
<!-- これらを追加 -->
<key>NSCameraUsageDescription</key>
<string>イベントの写真を撮影するためにカメラを使用します</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>イベントの写真を選択するためにフォトライブラリにアクセスします</string>
</dict>
💡 学んだこと
ケース4:本番ビルドだけエラーが出る
状況
flutter run --debug
✅ デバッグモード:完璧に動く
flutter build apk --release
❌ リリースビルド:エラー
🔍 調査ステップ1:エラーメッセージを確認
flutter build apk --release -v
```
**エラー:**
```
MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)
🔍調査ステップ2:ProGuardの確認
原因:難読化で必要なコードが削除された
android/app/build.gradle.kts を確認:
buildTypes {
release {
isMinifyEnabled = true // 難読化が有効
proguardFiles(...)
}
}
✅ 解決方法
android/app/proguard-rules.pro を作成:
# Flutter関連
-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.** { *; }
# Shared Preferences
-keep class * extends com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
再ビルド:
flutter clean
flutter build apk --release
💡 学んだこと
ケース5:パッケージ更新後に動かなくなった
状況
flutter pub upgrade
flutter run
エラー:
The method 'xxx' was called on null.
昨日まで動いていたのに… 😱
🔍 調査ステップ1:何が更新されたか確認
git diff pubspec.lock
出力
http:
- version: "1.1.0"
+ version: "1.2.0"
image_picker:
- version: "1.0.4"
+ version: "1.0.7"
image_pickerが破壊的変更をしている可能性!
🔍 調査ステップ2:CHANGELOGを確認
https://pub.dev/packages/image_picker/changelog
```
**1.0.5で変更:**
```
BREAKING CHANGE: pickImage() の戻り値が変更
- Before: File?
- After: XFile?
✅ 解決方法
コードを修正:
// 古いコード(動かない)
Future<void> _pickImage() async {
final ImagePicker picker = ImagePicker();
final File? image = await picker.pickImage(source: ImageSource.gallery);
// ↑ File? は使えない
}
// 新しいコード(修正後)
Future<void> _pickImage() async {
final ImagePicker picker = ImagePicker();
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
// ↑ XFile? に変更
if (image != null) {
File file = File(image.path); // File に変換
setState(() {
_selectedImage = file;
});
}
}
💡 学んだこと
🎯 トラブルシューティングの基本手順
黄金の7ステップ
→ エラーメッセージをコピー
→ git diff で確認
→ flutter doctor
→ flutter run -v
→ エラーメッセージで検索
→ flutter clean && flutter pub get
→ 一つずつ試す
🔧 実践的なデバッグテクニック
テクニック1:分割統治法
問題:どこでエラーが起きているか分からない
dart// コードをコメントアウトして絞り込む
void main() {
runApp(MyApp());
// loadData(); // まずこれをコメントアウト
// initDatabase(); // 次にこれ
}
一つずつ有効化して、どこで壊れるか特定
テクニック2:print デバッグ
Future fetchData() async {
print('=== fetchData 開始 ===');
try {
print('URL: $apiUrl');
final response = await http.get(Uri.parse(apiUrl));
print('Status: ${response.statusCode}');
print('Body: ${response.body}');
return response;
} catch (e) {
print('エラー: $e');
rethrow;
}
}
ログを追って、どこまで実行されたか確認
テクニック3:バージョンを戻す
パッケージ更新後に問題が出たら:
bash# 元に戻す
git checkout pubspec.lock
flutter pub get
動作確認
flutter run
動いたら、一つずつ更新
flutter pub upgrade http # 個別に更新
flutter pub upgrade image_picker
テクニック4:最小再現コードを作る
問題を切り離す:
// 最小限のコード
void main() {
runApp(MaterialApp(
home: Scaffold(
body: Center(
child: Text('テスト'),
),
),
));
}
これが動けば、Flutter環境は問題なし
📊 トラブルシューティング優先度
レベル1:まずこれを試す(90%解決)
bashflutter clean
flutter pub get
flutter run
レベル2:それでもダメなら(5%解決)
# キャッシュクリア
flutter pub cache repair
# Gradleクリア(Android)
cd android && ./gradlew clean && cd ..
# Podクリア(iOS)
cd ios && rm -rf Pods/ && pod install && cd ..
レベル3:詳しく調査(4%解決)
# 詳細ログ
flutter run -v
# 環境確認
flutter doctor -v
# Google検索
"flutter" + "エラーメッセージ"
レベル4:最終手段(1%解決)
# 完全リセット
rm -rf build/
rm -rf .dart_tool/
rm -rf android/.gradle/
rm -rf ios/Pods/
flutter clean
flutter pub get
💡 予防策
① Gitでバージョン管理
bash# こまめにコミット
git add .
git commit -m "機能追加:画像アップロード"
# 問題が出たら戻せる
git log # 履歴確認
git checkout HEAD~1 # 1つ前に戻る
② パッケージ更新は計画的に
bash# 更新前にバックアップ
git commit -am "パッケージ更新前"
# CHANGELOGを確認
# https://pub.dev/packages/[パッケージ名]/changelog
# 一つずつ更新
flutter pub upgrade http
flutter test # テスト
# 問題なければコミット
git add pubspec.lock
git commit -m "http を 1.2.0 に更新"
③ 定期的なメンテナンス
# 週1回
flutter clean
flutter pub get
flutter doctor
# 月1回
flutter upgrade # Flutter自体を更新
flutter pub outdated # 古いパッケージ確認
まとめ:トラブル解決
① パニックにならない
エラーは必ず解決できる
誰かが同じ問題に遭遇している
② 一つずつ試す
複数の変更を同時にしない
何を試したか記録する
③ ログを読む
エラーメッセージは友達
最初と最後をよく読む
④ Google検索を活用
“flutter” + エラーメッセージ
Stack Overflow を確認
GitHub Issues を確認
⑤ コミュニティに質問
Stack Overflow
Flutter Discord
GitHub Issues
🎊 今日のケーススタディまとめ
✅ ケース1:debug.keystore 再生成
✅ ケース2:ensureInitialized() 追加
✅ ケース3:iOS パーミッション設定
✅ ケース4:ProGuard 設定
✅ ケース5:パッケージ更新対応
